/*
 * Copyright (c) 2020 - 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 *
 * NVIDIA CORPORATION and its licensors retain all intellectual property
 * and proprietary rights in and to this software, related documentation
 * and any modifications thereto.  Any use, reproduction, disclosure or
 * distribution of this software and related documentation without an express
 * license agreement from NVIDIA CORPORATION is strictly prohibited.
 */

/**
 * @brief nvJPEG2000 library - GPU-accelerated JPEG 2000 encoding and decoding
 *
 * @file nvjpeg2k.h
 */

#ifndef NVJPEG2K_HEADER
#define NVJPEG2K_HEADER

#include <stdlib.h>
#include <stdint.h>

#ifdef _NVJPEG2K_DISABLE_CUDA_TOOLKIT_HEADERS
typedef void* cudaStream_t;
typedef enum libraryPropertyType_t
{
    MAJOR_VERSION,
    MINOR_VERSION,
    PATCH_LEVEL
} libraryPropertyType;
#else
#include "cuda_runtime_api.h"
#include "library_types.h"
#endif

#include "nvjpeg2k_version.h"

#define NVJPEG2KAPI

#if defined(__cplusplus)
  extern "C" {
#endif


/**
 * @brief Prototype for device memory allocation, modelled after @c cudaMalloc().
 *
 * Parameters: pointer to allocated memory (out), size in bytes to allocate (in).
 * @return 0 on success, non-zero on failure.
 */
typedef int (*nvjpeg2kDeviceMalloc)(void**, size_t);

/**
 * @brief Prototype for device memory release, modelled after @c cudaFree().
 *
 * Parameters: pointer to memory to free (in).
 * @return 0 on success, non-zero on failure.
 */
typedef int (*nvjpeg2kDeviceFree)(void*);

/**
 * @brief Prototype for pinned memory allocation, modelled after @c cudaHostAlloc().
 *
 * Parameters: pointer to allocated memory (out), size in bytes to allocate (in),
 * allocation flags (in).
 * @return 0 on success, non-zero on failure.
 */
typedef int (*nvjpeg2kPinnedMalloc)(void**, size_t, unsigned int flags);

/**
 * @brief Prototype for pinned memory release, modelled after @c cudaFreeHost().
 *
 * Parameters: pointer to memory to free (in).
 * @return 0 on success, non-zero on failure.
 */
typedef int (*nvjpeg2kPinnedFree)(void*);

/**
 * @brief Device memory allocator interface.
 *
 * When passed to @c nvjpeg2kCreate(), this structure is used for allocating and
 * releasing device memory. If @c NULL is passed instead, the default
 * @c cudaMalloc() / @c cudaFree() functions are used. When using
 * @c nvjpeg2kCreateSimple() to create the library handle, the default device
 * memory allocator will be used.
 */
typedef struct
{
    nvjpeg2kDeviceMalloc device_malloc; /**< Device memory allocation callback. */
    nvjpeg2kDeviceFree device_free;     /**< Device memory free callback. */
} nvjpeg2kDeviceAllocator_t;

/**
 * @brief Pinned memory allocator interface.
 *
 * When passed to @c nvjpeg2kCreate(), this structure is used for allocating and
 * releasing host pinned memory for copying data to/from device. If @c NULL is
 * passed instead, the default @c cudaHostAlloc() / @c cudaFreeHost() functions
 * are used. When using @c nvjpeg2kCreateSimple() to create the library handle,
 * the default host pinned memory allocator will be used.
 */
typedef struct
{
    nvjpeg2kPinnedMalloc pinned_malloc; /**< Pinned memory allocation callback. */
    nvjpeg2kPinnedFree   pinned_free;   /**< Pinned memory free callback. */
} nvjpeg2kPinnedAllocator_t;

/**
 * @brief Prototype for extended device memory allocation with stream and context.
 *
 * @param ctx [in] User-defined context pointer.
 * @param ptr [out] Pointer to allocated memory.
 * @param size [in] Size in bytes to allocate.
 * @param stream [in] CUDA stream for ordered allocation.
 * @return 0 on success, non-zero on failure.
 */
typedef int (*nvjpeg2kDeviceMallocV2)(void* ctx, void **ptr, size_t size, cudaStream_t stream);

/**
 * @brief Prototype for extended device memory release with stream and context.
 *
 * @param ctx [in] User-defined context pointer.
 * @param ptr [in] Pointer to memory to free.
 * @param size [in] Size in bytes of the allocation.
 * @param stream [in] CUDA stream for ordered deallocation.
 * @return 0 on success, non-zero on failure.
 */
typedef int (*nvjpeg2kDeviceFreeV2)(void* ctx, void *ptr, size_t size, cudaStream_t stream);

/**
 * @brief Prototype for extended pinned memory allocation with stream and context.
 *
 * @param ctx [in] User-defined context pointer.
 * @param ptr [out] Pointer to allocated memory.
 * @param size [in] Size in bytes to allocate.
 * @param stream [in] CUDA stream for ordered allocation.
 * @return 0 on success, non-zero on failure.
 */
typedef int (*nvjpeg2kPinnedMallocV2)(void* ctx, void **ptr, size_t size, cudaStream_t stream);

/**
 * @brief Prototype for extended pinned memory release with stream and context.
 *
 * @param ctx [in] User-defined context pointer.
 * @param ptr [in] Pointer to memory to free.
 * @param size [in] Size in bytes of the allocation.
 * @param stream [in] CUDA stream for ordered deallocation.
 * @return 0 on success, non-zero on failure.
 */
typedef int (*nvjpeg2kPinnedFreeV2)(void* ctx, void *ptr, size_t size, cudaStream_t stream);

/**
 * @brief Extended pinned memory allocator interface with stream and context support.
 *
 * Allows the user to provide pinned allocators which accept CUDA streams and
 * user context. Extended pinned allocators can be passed as input to the library
 * using @c nvjpeg2kCreateV2().
 */
typedef struct nvjpeg2kPinnedAllocatorV2
{
    nvjpeg2kPinnedMallocV2 pinned_malloc; /**< Extended pinned memory allocation callback. */
    nvjpeg2kPinnedFreeV2   pinned_free;   /**< Extended pinned memory free callback. */
    void *pinned_ctx;                     /**< User-defined context pointer. */
} nvjpeg2kPinnedAllocatorV2_t;

/**
 * @brief Extended device memory allocator interface with stream and context support.
 *
 * Allows the user to provide device allocators which accept CUDA streams and
 * user context. Extended device allocators can be passed as input to the library
 * using @c nvjpeg2kCreateV2().
 */
typedef struct nvjpeg2kDeviceAllocatorV2
{
    nvjpeg2kDeviceMallocV2 device_malloc; /**< Extended device memory allocation callback. */
    nvjpeg2kDeviceFreeV2 device_free;     /**< Extended device memory free callback. */
    void *device_ctx;                     /**< User-defined context pointer. */
} nvjpeg2kDeviceAllocatorV2_t;


/**
 * @brief Return status codes for nvJPEG2000 APIs.
 * @anchor nvjpeg2kStatus_t
 */
typedef enum
{
    NVJPEG2K_STATUS_SUCCESS                       = 0, /**< The API call finished successfully. Note that many calls are asynchronous and some errors may only appear after synchronization. */
    NVJPEG2K_STATUS_NOT_INITIALIZED               = 1, /**< The library handle was not initialized. */
    NVJPEG2K_STATUS_INVALID_PARAMETER             = 2, /**< Wrong parameter was passed. For example, a null pointer as input data, or an invalid enum value. */
    NVJPEG2K_STATUS_BAD_JPEG                      = 3, /**< Cannot parse the JPEG2000 stream. Likely due to a corruption that cannot be handled. */
    NVJPEG2K_STATUS_JPEG_NOT_SUPPORTED            = 4, /**< Attempting to decode a JPEG2000 stream that is not supported by the nvJPEG2000 library. */
    NVJPEG2K_STATUS_ALLOCATOR_FAILURE             = 5, /**< The user-provided allocator functions, for either memory allocation or for releasing the memory, returned a non-zero code. */
    NVJPEG2K_STATUS_EXECUTION_FAILED              = 6, /**< Error during the execution of the device tasks. */
    NVJPEG2K_STATUS_ARCH_MISMATCH                 = 7, /**< The device capabilities are not enough for the set of input parameters provided. */
    NVJPEG2K_STATUS_INTERNAL_ERROR                = 8, /**< Unknown error occurred in the library. */
    NVJPEG2K_STATUS_IMPLEMENTATION_NOT_SUPPORTED  = 9, /**< API is not supported by the backend. */
} nvjpeg2kStatus_t;

/**
 * @brief Backend selection for the nvJPEG2000 library.
 *
 * Allows the user to select a different internal implementation. A single
 * implementation is currently supported. Additional implementations may be
 * added in the future.
 */
typedef enum
{
    NVJPEG2K_BACKEND_DEFAULT = 0 /**< Default backend implementation. */
} nvjpeg2kBackend_t;

/**
 * @brief Color space values for JP2 files.
 *
 * Corresponds to the colorspace values which are part of the JP2 file format
 * specification.
 */
typedef enum
{
    NVJPEG2K_COLORSPACE_NOT_SUPPORTED = -1, /**< Color space is not supported. */
    NVJPEG2K_COLORSPACE_UNKNOWN       = 0,  /**< Color space is unknown. */
    NVJPEG2K_COLORSPACE_SRGB          = 1,  /**< sRGB color space. */
    NVJPEG2K_COLORSPACE_GRAY          = 2,  /**< Grayscale. */
    NVJPEG2K_COLORSPACE_SYCC          = 3   /**< sYCC color space. */
} nvjpeg2kColorSpace_t;

/**
 * @brief Per-component image information.
 *
 * Used to retrieve component level information. This information can be used
 * for allocating output buffers.
 */
typedef struct
{
    uint32_t component_width;  /**< Width of the component in pixels. */
    uint32_t component_height; /**< Height of the component in pixels. */
    uint8_t  precision;        /**< Bit depth of the component. */
    uint8_t  sgn;              /**< 1 if the component samples are signed, 0 otherwise. */
} nvjpeg2kImageComponentInfo_t;

/**
 * @brief Image-level information.
 *
 * Used to retrieve image information which can be used to allocate output
 * buffers.
 */
typedef struct
{
    uint32_t image_width;   /**< Width of the image in pixels. */
    uint32_t image_height;  /**< Height of the image in pixels. */
    uint32_t tile_width;    /**< Width of a tile in pixels. */
    uint32_t tile_height;   /**< Height of a tile in pixels. */
    uint32_t num_tiles_x;   /**< Number of tiles in the horizontal direction. */
    uint32_t num_tiles_y;   /**< Number of tiles in the vertical direction. */
    uint32_t num_components; /**< Number of image components. */
} nvjpeg2kImageInfo_t;

/**
 * @brief Pixel data types supported by nvJPEG2000.
 * @anchor nvjpeg2kImageType_t
 */
typedef enum
{
    NVJPEG2K_UINT8 = 0,  /**< Unsigned 8-bit integer. */
    NVJPEG2K_UINT16 = 1, /**< Unsigned 16-bit integer. */
    NVJPEG2K_INT16 = 2   /**< Signed 16-bit integer. */
} nvjpeg2kImageType_t;

/**
 * @brief Image memory layout format.
 *
 * Describes how an image is stored in memory.
 */
typedef enum
{
    NVJPEG2K_FORMAT_PLANAR = 0,      /**< All components are stored in separate planes. */
    NVJPEG2K_FORMAT_INTERLEAVED = 1  /**< All components are stored in interleaved order. Not supported when component dimensions differ. */
} nvjpeg2kImageFormat_t;

/**
 * @brief Image container for decode/encode operations.
 *
 * Contains an array of pointers, one per component, and a corresponding array
 * of pitch values. @c pixel_type determines the data type of @c pixel_data.
 */
typedef struct
{
    void **pixel_data;             /**< Array of pointers to component data in device memory. */
    size_t *pitch_in_bytes;        /**< Array of pitch values (in bytes) for each component. */
    nvjpeg2kImageType_t pixel_type; /**< Pixel data type. See @ref nvjpeg2kImageType_t "Image Type" for supported types. */
    uint32_t num_components;       /**< Number of image components. */
} nvjpeg2kImage_t;

/**
 * @brief Maximum number of JPEG2000 resolutions.
 */
#define NVJPEG2K_MAXRES 33

/**
 * @brief To enable High throughput JPEG2000 Encode, set @c rsiz in @c nvjpeg2kEncodeConfig_t to @c ::NVJPEG2K_RSIZ_HT
 */
#define NVJPEG2K_RSIZ_HT 0x4000

/**
 * @brief To enable High throughput JPEG2000 Encode, set @c encode_modes in @c nvjpeg2kEncodeConfig_t to @c ::NVJPEG2K_MODE_HT
 */
#define NVJPEG2K_MODE_HT 0x40

/**
 * @brief Progression orders defined in the JPEG2000 standard.
 */
typedef enum nvjpeg2kProgOrder
{
    NVJPEG2K_LRCP = 0, /**< Layer-Resolution-Component-Position. */
    NVJPEG2K_RLCP = 1, /**< Resolution-Layer-Component-Position. */
    NVJPEG2K_RPCL = 2, /**< Resolution-Position-Component-Layer. */
    NVJPEG2K_PCRL = 3, /**< Position-Component-Resolution-Layer. */
    NVJPEG2K_CPRL = 4  /**< Component-Position-Resolution-Layer. */
} nvjpeg2kProgOrder_t;

/**
 * @brief JPEG2000 bitstream type.
 *
 * @c ::NVJPEG2K_STREAM_J2K corresponds to the JPEG2000 codestream.
 * @c ::NVJPEG2K_STREAM_JP2 corresponds to the .jp2 container.
 */
typedef enum nvjpeg2kBitstreamType
{
    NVJPEG2K_STREAM_J2K  = 0, /**< JPEG2000 codestream (.j2k). */
    NVJPEG2K_STREAM_JP2  = 1  /**< JP2 container (.jp2). */
} nvjpeg2kBitstreamType_t;


/**
 * @brief JPEG2000 encode configuration.
 *
 * Contains parameters present in the COD and SIZ headers of the JPEG2000
 * bitstream. Not all parameters are supported and some must be set to 0.
 */
typedef struct
{
    nvjpeg2kBitstreamType_t stream_type;          /**< Bitstream type (J2K or JP2). */
    nvjpeg2kColorSpace_t color_space;             /**< Color space of the image. */
    uint16_t rsiz;                                /**< Should be set to 0 for J2K or @ref ::NVJPEG2K_RSIZ_HT for HTJ2K. */
    uint32_t image_width;                         /**< Image width in pixels. Minimum value 1. */
    uint32_t image_height;                        /**< Image height in pixels. Minimum value 1. */
    uint32_t enable_tiling;                       /**< Set to 1 to enable tiling, 0 to disable. */
    uint32_t tile_width;                          /**< Tile width. Valid only when @c enable_tiling is 1. Should be less than @c image_width. */
    uint32_t tile_height;                         /**< Tile height. Valid only when @c enable_tiling is 1. Should be less than @c image_height. */
    uint32_t num_components;                      /**< Number of image components (1-4). */
    nvjpeg2kImageComponentInfo_t *image_comp_info; /**< Pointer to per-component information. Must be a valid pointer. */
    uint32_t enable_SOP_marker;                   /**< Should be set to 0. */
    uint32_t enable_EPH_marker;                   /**< Should be set to 0. */
    nvjpeg2kProgOrder_t prog_order;               /**< Progression order. */
    uint32_t num_layers;                          /**< Number of quality layers. Should be set to 1. */
    uint32_t mct_mode;                            /**< Multi-component transform mode. 0 for YCC/Grayscale, 1 for RGB. */
    uint32_t num_resolutions;                     /**< Number of resolutions. Cannot be greater than image/tile dimensions. */
    uint32_t code_block_w;                        /**< Code block width. Valid values: 32, 64. */
    uint32_t code_block_h;                        /**< Code block height. Valid values: 32, 64. */
    uint32_t encode_modes;                        /**< Should be set to 0 for J2K or @ref ::NVJPEG2K_MODE_HT for HTJ2K. */
    uint32_t irreversible;                        /**< Set to 1 for irreversible (lossy) transform, 0 for reversible (lossless). */
    uint32_t num_precincts_init;                  /**< Number of valid precinct entries. Set to 0 to disable custom precincts. */
    uint32_t precinct_width[NVJPEG2K_MAXRES];     /**< Precinct widths per resolution. Should be a power of 2. Valid only when @c num_precincts_init is non-zero. */
    uint32_t precinct_height[NVJPEG2K_MAXRES];    /**< Precinct heights per resolution. Should be a power of 2. Valid only when @c num_precincts_init is non-zero. */
} nvjpeg2kEncodeConfig_t;

/**
 * @brief Quality type selection for lossy encoding.
 * @anchor nvjpeg2kQualityType_t
 *
 * Can be used with @c nvjpeg2kEncodeParamsSpecifyQuality().
 */
typedef enum nvjpeg2kQualityType
{
    NVJPEG2K_QUALITY_TYPE_TARGET_PSNR = 0,       /**< Quality value is interpreted as desired Peak Signal-to-Noise Ratio (PSNR) target. The higher the value, the better quality image is produced. Quality value should be positive floating point. Cannot be used with HT encoder. */
    NVJPEG2K_QUALITY_TYPE_QUANTIZATION_STEP = 1,  /**< Quality value is interpreted as quantization step (by how much pixel data will be divided). The higher the value, the worse quality image is produced. Quality value should be positive floating point. */
    NVJPEG2K_QUALITY_TYPE_Q_FACTOR = 2            /**< Quality value is interpreted as JPEG-like quality factor (1.0 worst to 100.0 best). Can only be used when the input colorspace is YCC, Grayscale, or RGB with MCT enabled. */
} nvjpeg2kQualityType_t;

/**
 * @brief Opaque nvJPEG2000 library handle.
 */
struct nvjpeg2kHandle;

/**
 * @brief Handle to the nvJPEG2000 library instance.
 *
 * This handle should be instantiated prior to using any of the decode APIs.
 * It is thread safe and can be used by multiple threads simultaneously.
 */
typedef struct nvjpeg2kHandle* nvjpeg2kHandle_t;

/**
 * @brief Opaque nvJPEG2000 decode state.
 */
struct nvjpeg2kDecodeState;

/**
 * @brief Handle to the nvJPEG2000 decode state.
 *
 * Stores intermediate decode information. This handle can be reused when
 * decoding multiple images. The user must ensure that a stream or device
 * synchronize CUDA call is made between the decoding of two images.
 */
typedef struct nvjpeg2kDecodeState* nvjpeg2kDecodeState_t;

/**
 * @brief Opaque nvJPEG2000 bitstream handle.
 */
struct nvjpeg2kStream;

/**
 * @brief Handle to the nvJPEG2000 bitstream.
 *
 * Used for parsing the bitstream. Bitstream metadata can be extracted
 * by using the APIs defined in @ref ParserAPIReference "Parser API Reference".
 */
typedef struct nvjpeg2kStream* nvjpeg2kStream_t;

/**
 * @brief Opaque nvJPEG2000 decode parameters.
 */
struct nvjpeg2kDecodeParams;

/**
 * @brief Handle to the nvJPEG2000 decode output parameters.
 *
 * Used to store the decode output parameters like the decode area of interest
 * coordinates.
 */
typedef struct nvjpeg2kDecodeParams* nvjpeg2kDecodeParams_t;


/**
 * @brief Opaque nvJPEG2000 encoder handle.
 */
struct nvjpeg2kEncoder;

/**
 * @brief Handle to the nvJPEG2000 encoder instance.
 *
 * This handle should be instantiated prior to using any of the encode APIs.
 * It is thread safe and can be used across host threads.
 */
typedef struct nvjpeg2kEncoder* nvjpeg2kEncoder_t;

/**
 * @brief Opaque nvJPEG2000 encode state.
 */
struct nvjpeg2kEncodeState;

/**
 * @brief Handle to the nvJPEG2000 encode state.
 *
 * Contains intermediate buffers required by the encoding process.
 */
typedef struct nvjpeg2kEncodeState* nvjpeg2kEncodeState_t;

/**
 * @brief Opaque nvJPEG2000 encode parameters.
 */
struct nvjpeg2kEncodeParams;

/**
 * @brief Handle to the nvJPEG2000 encode parameters.
 *
 * Stores user provided parameters that control the encoding process.
 */
typedef struct nvjpeg2kEncodeParams* nvjpeg2kEncodeParams_t;

/**
 * @brief Get the CUDA Toolkit version used to build the library.
 *
 * Returns the numeric value for the major version, minor version, or the
 * patch level of the CUDA toolkit that was used to build the nvJPEG2000
 * library.
 *
 * @param type [in] Version type: @c MAJOR_VERSION, @c MINOR_VERSION, or @c PATCH_LEVEL.
 * @param value [out] The numeric value corresponding to the requested property.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kGetCudartProperty(libraryPropertyType type, int *value);

/**
 * @brief Get the nvJPEG2000 library version.
 *
 * Returns the numeric value for the major version, minor version, or the
 * patch level of the nvJPEG2000 library.
 *
 * @param type [in] Version type: @c MAJOR_VERSION, @c MINOR_VERSION, or @c PATCH_LEVEL.
 * @param value [out] The numeric value corresponding to the requested property.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kGetProperty(libraryPropertyType type, int *value);

/**
 * @brief Create an nvJPEG2000 library handle with default settings.
 *
 * Creates an instance of the library handle with default backend and memory
 * allocators.
 *
 * @param handle [in/out] Pointer to the library handle to initialize.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kCreateSimple(nvjpeg2kHandle_t *handle);

/**
 * @brief Create an nvJPEG2000 library handle with custom allocators.
 *
 * Creates an instance of the library using the input arguments. The user has
 * flexibility to choose the backend implementation and provide allocators.
 *
 * @param backend [in] Backend to use. Currently @c ::NVJPEG2K_BACKEND_DEFAULT is supported.
 * @param device_allocator [in] See @c nvjpeg2kDeviceAllocator_t. If @c NULL, default @c cudaMalloc() / @c cudaFree() are used.
 * @param pinned_allocator [in] See @c nvjpeg2kPinnedAllocator_t. If @c NULL, default @c cudaHostAlloc() / @c cudaFreeHost() are used.
 * @param handle [in/out] Pointer to the library handle to initialize.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kCreate(
        nvjpeg2kBackend_t backend,
        nvjpeg2kDeviceAllocator_t *device_allocator,
        nvjpeg2kPinnedAllocator_t *pinned_allocator,
        nvjpeg2kHandle_t *handle);

/**
 * @brief Create an nvJPEG2000 library handle with extended custom allocators.
 *
 * Creates an instance of the library using extended allocators that accept
 * CUDA streams and user context.
 *
 * @param backend [in] Backend to use. Currently @c ::NVJPEG2K_BACKEND_DEFAULT is supported.
 * @param dev_allocator [in] See @c nvjpeg2kDeviceAllocatorV2_t. Cannot be @c NULL.
 * @param pinned_allocator [in] See @c nvjpeg2kPinnedAllocatorV2_t. Cannot be @c NULL.
 * @param handle [in/out] Pointer to the library handle to initialize.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kCreateV2(nvjpeg2kBackend_t backend,
        nvjpeg2kDeviceAllocatorV2_t *dev_allocator,
        nvjpeg2kPinnedAllocatorV2_t *pinned_allocator,
        nvjpeg2kHandle_t *handle);

/**
 * @brief Release the nvJPEG2000 library handle and resources.
 *
 * @param handle [in] Library handle to release.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kDestroy(nvjpeg2kHandle_t handle);

/**
 * @brief Set padding for device memory allocations.
 *
 * After success on this call, any device memory allocation would be padded to
 * the multiple of specified number of bytes. This helps minimize the number of
 * device memory reallocations.
 *
 * @param padding [in] Padding size in bytes.
 * @param handle [in/out] Library handle.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kSetDeviceMemoryPadding(
        size_t padding,
        nvjpeg2kHandle_t handle);

/**
 * @brief Retrieve padding for device memory allocations.
 *
 * @param padding [out] Current device memory padding size in bytes.
 * @param handle [in] Library handle.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kGetDeviceMemoryPadding(
        size_t *padding,
        nvjpeg2kHandle_t handle);

/**
 * @brief Set padding for pinned host memory allocations.
 *
 * After success on this call, any pinned host memory allocation would be padded
 * to the multiple of specified number of bytes. This helps minimize the number
 * of pinned memory reallocations.
 *
 * @param padding [in] Padding size in bytes.
 * @param handle [in/out] Library handle.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kSetPinnedMemoryPadding(
        size_t padding,
        nvjpeg2kHandle_t handle);

/**
 * @brief Retrieve padding for pinned host memory allocations.
 *
 * @param padding [out] Current pinned memory padding size in bytes.
 * @param handle [in] Library handle.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kGetPinnedMemoryPadding(
        size_t *padding,
        nvjpeg2kHandle_t handle);


/**
 * @brief Create an instance of the decode state.
 *
 * @param handle [in] Library handle.
 * @param decode_state [in/out] Pointer to the decode state handle to initialize.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kDecodeStateCreate(
        nvjpeg2kHandle_t handle,
        nvjpeg2kDecodeState_t *decode_state);

/**
 * @brief Release the decode state handle.
 *
 * @param decode_state [in] Decode state handle to release.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kDecodeStateDestroy(nvjpeg2kDecodeState_t decode_state);

/**
 * @brief Create an instance of the bitstream handle.
 *
 * @param stream_handle [in/out] Pointer to the bitstream handle to initialize.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kStreamCreate(nvjpeg2kStream_t *stream_handle);

/**
 * @brief Release the bitstream handle.
 *
 * @param stream_handle [in] Bitstream handle to release.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kStreamDestroy(nvjpeg2kStream_t stream_handle);

/**
 * @brief Parse a JPEG2000 bitstream from a host memory buffer.
 * @anchor ParserAPIReference
 *
 * This function is the first step in decoding a JPEG2000 bitstream. It accepts
 * the bitstream buffer on host memory as input and parses the JPEG2000 header
 * information. The parsed information is stored in the stream handle and can be
 * retrieved by the stream query APIs.
 *
 * @param handle [in] Library handle.
 * @param data [in] Pointer to the JPEG2000 bitstream buffer in host memory.
 * @param length [in] Size of the bitstream in bytes.
 * @param save_metadata [in] Reserved for future use. Set to 0.
 * @param save_stream [in] Reserved for future use. Set to 0.
 * @param stream_handle [in] Bitstream handle to store parsed information.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kStreamParse(nvjpeg2kHandle_t handle,
        const unsigned char *data,
        size_t length,
        int save_metadata,
        int save_stream,
        nvjpeg2kStream_t stream_handle);

/**
 * @brief Parse a JPEG2000 file from disk.
 *
 * Accepts a JPEG2000 file on disk as input and parses the JPEG2000 header
 * information. The parsed information is stored in the stream handle and can
 * be retrieved by the stream query APIs.
 *
 * @param handle [in] Library handle.
 * @param filename [in] Path to the JPEG2000 file on disk.
 * @param stream_handle [in] Bitstream handle to store parsed information.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kStreamParseFile(nvjpeg2kHandle_t handle,
        const char *filename,
        nvjpeg2kStream_t stream_handle);

/**
 * @brief Retrieve image-level information from a parsed bitstream.
 *
 * Retrieves the image information defined in @c nvjpeg2kImageInfo_t. This
 * information is useful in allocating output buffers on device memory.
 *
 * @param stream_handle [in] Bitstream handle.
 * @param image_info [out] Pointer to @c nvjpeg2kImageInfo_t to store the image information.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kStreamGetImageInfo(nvjpeg2kStream_t stream_handle,
        nvjpeg2kImageInfo_t* image_info);

/**
 * @brief Retrieve component-level information from a parsed bitstream.
 *
 * Retrieves the component level information defined in
 * @c nvjpeg2kImageComponentInfo_t. This information can be used in allocating
 * output buffers on device memory. Component level information is useful when
 * the dimensions vary across components.
 *
 * @param stream_handle [in] Bitstream handle.
 * @param component_info [out] Pointer to @c nvjpeg2kImageComponentInfo_t to store the component information.
 * @param component_id [in] Component index.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kStreamGetImageComponentInfo(nvjpeg2kStream_t stream_handle,
        nvjpeg2kImageComponentInfo_t* component_info,
        uint32_t component_id);

/**
 * @brief Retrieve the number of resolutions present in a tile.
 *
 * The number of resolutions is defined as:
 * <tt>numResolutions = numWaveletDecompositionLevels + 1</tt>.
 * Tiles in JPEG2000 are indexed in raster scan order.
 * @c nvjpeg2kStreamGetImageInfo() retrieves the number of tiles present
 * along both the x and y directions. For tile coordinates tile_x, tile_y:
 * <tt>tile_id = tile_y * num_tiles_x + tile_x</tt>.
 *
 * @param stream_handle [in] Bitstream handle.
 * @param tile_id [in] Raster scan based tile index.
 * @param num_res [out] Number of resolutions present in the tile.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kStreamGetResolutionsInTile(nvjpeg2kStream_t stream_handle,
        uint32_t tile_id,
        uint32_t* num_res);

/**
 * @brief Retrieve tile dimensions for a tile component.
 *
 * This function is useful when the tile dimensions in @c nvjpeg2kImageInfo_t are
 * not a multiple of the image dimensions.
 *
 * @param stream_handle [in] Bitstream handle.
 * @param component_id [in] Component index.
 * @param tile_id [in] Raster scan based tile index.
 * @param tile_width [out] Tile width for the specified tile component.
 * @param tile_height [out] Tile height for the specified tile component.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kStreamGetTileComponentDim(nvjpeg2kStream_t stream_handle,
        uint32_t component_id,
        uint32_t tile_id,
        uint32_t* tile_width,
        uint32_t* tile_height);

/**
 * @brief Retrieve dimensions at a resolution level for a tile component.
 *
 * The resolution dimensions are computed as follows:
 * - <tt>res_scale = 1 << (num_resolutions - res_level - 1)</tt>
 * - <tt>res_width = (tile_width + res_scale - 1) >> res_scale</tt>
 * - <tt>res_height = (tile_height + res_scale - 1) >> res_scale</tt>
 *
 * @param stream_handle [in] Bitstream handle.
 * @param component_id [in] Component index.
 * @param tile_id [in] Raster scan based tile index.
 * @param res_level [in] Resolution level.
 * @param res_width [out] Resolution width for the specified tile component and resolution level.
 * @param res_height [out] Resolution height for the specified tile component and resolution level.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kStreamGetResolutionComponentDim(nvjpeg2kStream_t stream_handle,
        uint32_t component_id,
        uint32_t tile_id,
        uint32_t res_level,
        uint32_t* res_width,
        uint32_t* res_height );

/**
 * @brief Retrieve color space information from a parsed JP2 file.
 *
 * For a JPEG2000 codestream (.j2k file), this function will retrieve
 * @c ::NVJPEG2K_COLORSPACE_UNKNOWN since color space information is not available.
 *
 * @param stream_handle [in] Bitstream handle.
 * @param color_space [out] Color space of the parsed image.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kStreamGetColorSpace(nvjpeg2kStream_t stream_handle,
        nvjpeg2kColorSpace_t* color_space);

/**
 * @brief Create an instance of the decode output parameters handle.
 *
 * @param decode_params [in/out] Pointer to the decode parameters handle to initialize.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kDecodeParamsCreate(
        nvjpeg2kDecodeParams_t *decode_params);

/**
 * @brief Release the decode output parameters handle.
 *
 * @param decode_params [in] Decode parameters handle to release.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kDecodeParamsDestroy(nvjpeg2kDecodeParams_t decode_params);


/**
 * @brief Set the decode area of interest.
 *
 * The coordinates are relative to the image origin and should be within the
 * tile of interest. If the coordinates are set to 0, the entire tile will be
 * decoded.
 *
 * @param decode_params [in/out] Decode parameters handle.
 * @param start_x [in] Left coordinate of the decode area.
 * @param end_x [in] Right coordinate of the decode area.
 * @param start_y [in] Top coordinate of the decode area.
 * @param end_y [in] Bottom coordinate of the decode area.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kDecodeParamsSetDecodeArea(nvjpeg2kDecodeParams_t decode_params,
        uint32_t start_x,
        uint32_t end_x,
        uint32_t start_y,
        uint32_t end_y);

/**
 * @brief Enable RGB decode output for chroma-subsampled images.
 *
 * Enables RGB decode output for images with 422/420 chroma subsampling. It is
 * ignored for other chroma subsampling values. YCC to RGB conversion is based
 * on sYCC, Amendment 1 to IEC 61966-2-1. The color conversion is applied at a
 * tile granularity due to which the chroma reconstruction may not be accurate
 * for tiles with odd dimensions.
 *
 * @param decode_params [in/out] Decode parameters handle.
 * @param force_rgb [in] Set to 1 to enable RGB output.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kDecodeParamsSetRGBOutput(nvjpeg2kDecodeParams_t decode_params,
        int32_t force_rgb);

/**
 * @brief Set the decode output format.
 *
 * Sets the decode output format. When using @c ::NVJPEG2K_FORMAT_INTERLEAVED with
 * 420/422 chroma subsampling, RGB output (@c nvjpeg2kDecodeParamsSetRGBOutput())
 * must also be enabled.
 *
 * The decode output buffer should be allocated in the following manner to support
 * @c ::NVJPEG2K_FORMAT_INTERLEAVED:
 *
 * @code{.cpp}
 * nvjpeg2kImage_t decode_output;
 *
 * // When decode_output.pixel_type is NVJPEG2K_UINT8:  bytes_per_sample = 1
 * // When decode_output.pixel_type is NVJPEG2K_UINT16 or NVJPEG2K_INT16: bytes_per_sample = 2
 *
 * decode_output.pitch_in_bytes[0] = image_width * num_components * bytes_per_sample;
 * decode_output.pixel_data[0]     = decode_output.pitch_in_bytes[0] * info.image_height;
 * decode_output.num_components    = num_components;
 * @endcode
 *
 * @param decode_params [in/out] Decode parameters handle.
 * @param format [in] Output format. Defaults to @c ::NVJPEG2K_FORMAT_PLANAR.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kDecodeParamsSetOutputFormat(nvjpeg2kDecodeParams_t decode_params,
        nvjpeg2kImageFormat_t format);

/**
 * @brief Decode a single JPEG2000 image.
 *
 * Decodes a single image and writes it to the output device buffers. The
 * function is asynchronous with respect to the host. All GPU tasks will be
 * submitted to the provided @c stream. Prior to calling this function, the user
 * must parse the bitstream using @c nvjpeg2kStreamParse() such that the bitstream
 * information is stored in @c jpeg2k_stream.
 *
 * @param handle [in] Library handle.
 * @param decode_state [in] Decode state handle.
 * @param jpeg2k_stream [in] Bitstream handle with parsed information.
 * @param decode_output [in/out] Decode output struct. The struct should be on host memory. The image component pointers should point to device memory. See @c nvjpeg2kImage_t.
 * @param stream [in] CUDA stream. Can be set to 0.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kDecode(nvjpeg2kHandle_t handle,
        nvjpeg2kDecodeState_t decode_state,
        nvjpeg2kStream_t jpeg2k_stream,
        nvjpeg2kImage_t* decode_output,
        cudaStream_t stream);

/**
 * @brief Decode a single JPEG2000 image with decode parameters.
 *
 * Decodes a single image and writes it to the output device buffers. The
 * function is asynchronous with respect to the host. All GPU tasks will be
 * submitted to the provided @c stream. Prior to calling this function, the user
 * must parse the bitstream using @c nvjpeg2kStreamParse() such that the bitstream
 * information is stored in @c jpeg2k_stream. It is possible to control the
 * decode output using an instance of @c ::nvjpeg2kDecodeParams_t.
 *
 * @param handle [in] Library handle.
 * @param decode_state [in] Decode state handle.
 * @param jpeg2k_stream [in] Bitstream handle with parsed information.
 * @param decode_params [in] Decode parameters to control output (e.g. area of interest, RGB output). Can be set to @c NULL.
 * @param decode_output [in/out] Decode output struct. The struct should be on host memory. The image component pointers should point to device memory. See @c nvjpeg2kImage_t.
 * @param stream [in] CUDA stream. Can be set to 0.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kDecodeImage(nvjpeg2kHandle_t handle,
        nvjpeg2kDecodeState_t decode_state,
        nvjpeg2kStream_t jpeg2k_stream,
        nvjpeg2kDecodeParams_t decode_params,
        nvjpeg2kImage_t* decode_output,
        cudaStream_t stream);

/**
 * @brief Decode a single tile within a JPEG2000 image.
 *
 * Decodes a tile within an image and writes it to the output device buffers.
 * The function is asynchronous with respect to the host. All GPU tasks will be
 * submitted to the provided @c stream. Prior to calling this function, the user
 * must parse the bitstream using @c nvjpeg2kStreamParse() such that the bitstream
 * information is stored in @c jpeg2k_stream.
 *
 * @param handle [in] Library handle.
 * @param decode_state [in] Decode state handle.
 * @param jpeg2k_stream [in] Bitstream handle with parsed information.
 * @param decode_params [in] Decode parameters to control output. Can be set to @c NULL.
 * @param tile_id [in] Raster scan based tile index.
 * @param num_res_levels [in] Number of resolutions to decode within the tile. When set to 0, the image is decoded at full resolution. Maximum allowed resolutions in a tile can be determined using @c nvjpeg2kStreamGetResolutionsInTile().
 * @param decode_output [in/out] Decode output struct. The struct should be on host memory. The image component pointers should point to device memory. See @c nvjpeg2kImage_t.
 * @param stream [in] CUDA stream. Can be set to 0.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kDecodeTile(nvjpeg2kHandle_t handle,
        nvjpeg2kDecodeState_t decode_state,
        nvjpeg2kStream_t jpeg2k_stream,
        nvjpeg2kDecodeParams_t decode_params,
        uint32_t tile_id,
        uint32_t num_res_levels,
        nvjpeg2kImage_t* decode_output,
        cudaStream_t stream);


/**
 * @brief Create an nvJPEG2000 encoder handle with default settings.
 *
 * @param enc_handle [in/out] Pointer to the encoder handle to initialize.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kEncoderCreateSimple(nvjpeg2kEncoder_t *enc_handle);

/**
 * @brief Release the nvJPEG2000 encoder handle.
 *
 * @param enc_handle [in] Encoder handle to release.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kEncoderDestroy(nvjpeg2kEncoder_t enc_handle);

/**
 * @brief Create an instance of the encode state.
 *
 * @param enc_handle [in] Encoder handle.
 * @param encode_state [in/out] Pointer to the encode state handle to initialize.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kEncodeStateCreate(
        nvjpeg2kEncoder_t enc_handle,
        nvjpeg2kEncodeState_t *encode_state);

/**
 * @brief Release the encode state handle.
 *
 * @param encode_state [in] Encode state handle to release.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kEncodeStateDestroy(nvjpeg2kEncodeState_t encode_state);

/**
 * @brief Create an instance of the encode parameters handle.
 *
 * @param encode_params [in/out] Pointer to the encode parameters handle to initialize.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kEncodeParamsCreate(nvjpeg2kEncodeParams_t *encode_params);

/**
 * @brief Release the encode parameters handle.
 *
 * @param encode_params [in] Encode parameters handle to release.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kEncodeParamsDestroy(nvjpeg2kEncodeParams_t encode_params);

/**
 * @brief Set the JPEG2000 encode configuration.
 *
 * Sets the JPEG2000 header parameters defined in @c nvjpeg2kEncodeConfig_t. This
 * function should always be called during the encode process.
 *
 * @param encode_params [in/out] Encode parameters handle.
 * @param encoder_config [in] Pointer to @c nvjpeg2kEncodeConfig_t.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kEncodeParamsSetEncodeConfig(nvjpeg2kEncodeParams_t encode_params,
        nvjpeg2kEncodeConfig_t* encoder_config);

/**
 * @brief Set quality type and value for lossy encoding.
 *
 * Allows the application to set quality type (algorithm) and quality value,
 * which controls how good the encoded image should look. Refer to
 * @ref nvjpeg2kQualityType_t "nvjpeg2kQualityType_t" for the allowed values for each quality type. Will
 * overwrite any existing quality setting.
 *
 * @c nvjpeg2kEncodeParamsSetEncodeConfig() should be called before this function.
 *
 * Will return @c ::NVJPEG2K_STATUS_INVALID_PARAMETER if:
 * - @c nvjpeg2kEncodeParamsSetEncodeConfig() was not yet called
 * - @c quality_value is negative
 * - Encoding mode is set to reversible
 * - Quality type is @c ::NVJPEG2K_QUALITY_TYPE_TARGET_PSNR and HT encoder is enabled
 * - Quality type is @c ::NVJPEG2K_QUALITY_TYPE_Q_FACTOR and @c quality_value is larger than 100
 * - Quality type is @c ::NVJPEG2K_QUALITY_TYPE_Q_FACTOR and @c mct = 0 and input color space is sRGB
 *
 * @param encode_params [in/out] Encode parameters handle.
 * @param quality_type [in] Quality type (algorithm) to use. See @ref nvjpeg2kQualityType_t "nvjpeg2kQualityType_t".
 * @param quality_value [in] Quality value. Interpretation depends on @c quality_type.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kEncodeParamsSpecifyQuality(nvjpeg2kEncodeParams_t encode_params,
        nvjpeg2kQualityType_t quality_type, double quality_value);

/**
 * @brief Set the encode input format.
 *
 * Sets the encode input format. @c ::NVJPEG2K_FORMAT_INTERLEAVED is supported by
 * the encoder only when all component dimensions are the same.
 *
 * The encode input buffer should be allocated in the following manner to support
 * @c ::NVJPEG2K_FORMAT_INTERLEAVED:
 *
 * @code{.cpp}
 * nvjpeg2kImage_t encode_input;
 *
 * // When encode_input.pixel_type is NVJPEG2K_UINT8:  bytes_per_sample = 1
 * // When encode_input.pixel_type is NVJPEG2K_UINT16 or NVJPEG2K_INT16: bytes_per_sample = 2
 *
 * encode_input.pitch_in_bytes[0] = image_width * num_components * bytes_per_sample;
 * encode_input.pixel_data[0]     = encode_input.pitch_in_bytes[0] * info.image_height;
 * encode_input.num_components    = num_components;
 * @endcode
 *
 * @param encode_params [in/out] Encode parameters handle.
 * @param format [in] Input format. Defaults to @c ::NVJPEG2K_FORMAT_PLANAR.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kEncodeParamsSetInputFormat(nvjpeg2kEncodeParams_t encode_params,
        nvjpeg2kImageFormat_t format);

/**
 * @brief Compress an image in JPEG2000 format.
 *
 * Compresses the input image in JPEG2000 format and stores it within
 * @c encode_state. All GPU tasks will be submitted to the provided @c stream.
 * The function is asynchronous with respect to the host.
 *
 * @param enc_handle [in] Encoder handle.
 * @param encode_state [in] Encode state handle containing intermediate buffers.
 * @param encode_params [in] Encode parameters handle.
 * @param input_image [in] Input image. The struct should be on host memory. The image component pointers should point to device memory. See @c nvjpeg2kImage_t.
 * @param stream [in] CUDA stream for all device operations.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kEncode(nvjpeg2kEncoder_t enc_handle,
        nvjpeg2kEncodeState_t encode_state,
        const nvjpeg2kEncodeParams_t encode_params,
        const nvjpeg2kImage_t *input_image,
        cudaStream_t stream);


/**
 * @brief Retrieve the compressed JPEG2000 bitstream.
 *
 * Retrieves the compressed stream from the encoder state that was previously
 * used by the encoder function.
 *
 * - If @c compressed_data is @c NULL, the encoder will return the compressed
 *   JPEG2000 bitstream size in the @c length parameter.
 * - If @c compressed_data is not @c NULL, the @c length parameter should
 *   contain the data buffer size. If the length is less than the compressed
 *   stream size, an error will be returned. Otherwise the compressed stream
 *   will be stored in the data buffer and the actual compressed buffer size
 *   will be stored in @c length.
 * - When @c compressed_data is @c NULL, the API is synchronous with the host.
 * - When @c compressed_data is not @c NULL, the application should call
 *   @c cudaStreamSynchronize() to ensure the bitstream copy is successful.
 *
 * @param enc_handle [in] Encoder handle.
 * @param encode_state [in] Encode state handle.
 * @param compressed_data [out] Pointer to the host buffer for the compressed stream. Can be @c NULL (see description).
 * @param length [in/out] Pointer to the buffer size. The library will update the actual compressed stream size.
 * @param stream [in] CUDA stream for device operations.
 * @return An error code as specified in
 *         @ref nvjpeg2kStatus_t "API Return Status Codes".
 */
nvjpeg2kStatus_t NVJPEG2KAPI nvjpeg2kEncodeRetrieveBitstream(nvjpeg2kEncoder_t enc_handle,
          nvjpeg2kEncodeState_t encode_state,
          unsigned char *compressed_data,
          size_t *length,
          cudaStream_t stream);

#if defined(__cplusplus)
  }
#endif

#endif
