chimera::image::resize is a general-purpose tensor resize. It resizes each channel independently, supports nearest-neighbor and bilinear interpolation, and works on both OCM-resident and DDR-resident tensors. The DDR variants stream channels through OCM and can distribute the work across all cores. The API is provided by image.hpp (included via qil.h); the configuration enums live in image_resize_helpers.hpp.
Specialized overloads are selected at compile time from the ResizeMethod and the tensor locations, so the same call site dispatches to the best implementation for the shapes involved.
Resize Methods & Coordinate Transforms
/src/image_resize_helpers.hppLines 11–61 /**
* @brief Resize methods.
*
* NEAREST_NEIGHBORS: Nearest neighbor interpolation.
* BILINEAR_INTERPOLATION: Bilinear interpolation.
* BILINEAR_INTERPOLATION_MULTISTEP: Pyramid method using a series of bilinear interpolations. Downscales by 2 at a
* time. Reduces aliasing for large downscaling.
* BILINEAR_INTERPOLATION_HALF_PIXEL: Bilinear interpolation with half pixel offset. Deprecated in favor of using
* ResizeMethod::BILINEAR_INTERPOLATION with CoordinateTranform::HALF_PIXEL
* BILINEAR_INTERPOLATION_ASYMMETRIC: Bilinear interpolation without offset. Deprecated in favor of using
* ResizeMethod::BILINEAR_INTERPOLATION with CoordinateTranform::ASYMMETRIC
*
*/
enum class ResizeMethod {
NEAREST_NEIGHBORS = 0,
BILINEAR_INTERPOLATION,
BILINEAR_INTERPOLATION_MULTISTEP,
BILINEAR_INTERPOLATION_HALF_PIXEL QUADRIC_DEPRECATED_FUNCTION(
"Use BILINEAR_INTERPOLATION with CoordinateTransform mode HALF_PIXEL instead.", "2026-02-24", "26.04"),
BILINEAR_INTERPOLATION_ASYMMETRIC QUADRIC_DEPRECATED_FUNCTION(
"Use BILINEAR_INTERPOLATION with CoordinateTransform mode ASYMMETRIC instead.", "2026-02-24", "26.04"),
};
/**
* @brief Coordinate transform methods.
*
* ASYMMETRIC: Directly use image indices for internal calculations.
* HALF_PIXEL: Use half pixel offset to consider pixel values to be at the center of a pixel.
*
*/
enum class CoordinateTransform { ASYMMETRIC = 0, HALF_PIXEL, ALIGN_CORNERS };
/**
* @brief Internal rounding method to be used to calculate pixels for nearest neighbor interpolation.
*
* ROUND_PREFER_FLOOR: Round down when the decimal portion <= 0.5. Otherwise round up.
* ROUND_PREFER_CEIL: Round down when the decimal poriton < 0.5. Otherwise round up.
* FLOOR: Always take the floor.
* CEIL: ALways take the ceiling.
*
*/
enum class NearestMode { ROUND_PREFER_FLOOR = 0, ROUND_PREFER_CEIL, FLOOR, CEIL };
/**
* @brief Rounding method to use for integer outputs of bilinear resize methods.
*
* ROUND: Round the final output using math::RoundMethod::towardsPositiveInfinity.
* CAST: Mimic float to int casting.
*
*/
enum class IntRoundMethod { ROUND = 0, CAST };
The template parameters mirror the ONNX Resize attributes:
| Parameter | Applies to | Values | Default |
|---|---|---|---|
resizeMethod | all | NEAREST_NEIGHBORS, BILINEAR_INTERPOLATION | BILINEAR_INTERPOLATION |
coordinateTransform | all | ASYMMETRIC, HALF_PIXEL, ALIGN_CORNERS | HALF_PIXEL (bilinear), ASYMMETRIC (nearest) |
nearestMode | NEAREST_NEIGHBORS only | ROUND_PREFER_FLOOR, ROUND_PREFER_CEIL, FLOOR, CEIL | ROUND_PREFER_FLOOR |
intRoundMethod | BILINEAR_INTERPOLATION only | ROUND, CAST | ROUND |
multicoreMode | DDR overloads only | Single, All | Single |
Note:
BILINEAR_INTERPOLATION_HALF_PIXELandBILINEAR_INTERPOLATION_ASYMMETRICare deprecated. UseBILINEAR_INTERPOLATIONwith the matchingCoordinateTransforminstead.
OCM → OCM Resize
Resizes a planar OCM tensor of shape (1, channels, height, width) into an OCM tensor of shape (1, channels, resized_height, resized_width). The allocator parameter defaults to EmptyType — no scratch OCM is required.
Bilinear interpolation:
/src/image.hppLines 2432–2462 /**
* @brief General purpose tensor resize.
*
* Input tensor shape must be of form (1, channels, height, width).
* Output tensor shape must be of form (1, channels, resized_height, resized_width)
* @tparam resizeMethod Selection of resize method.
* @tparam coordinateTransform Selection of coordinate transform method.
* @tparam nearestMode Selection of internal rounding method. Only applicable for NEAREST_NEIGHBORS.
* @tparam intRoundMode Selection for output int rounding method. Only applicable for BILINEAR_INTERPOLATION.
* @tparam OcmAllocatorType Type of ocm allocator.
* @tparam OcmInputShape The shape of the input tensor.
* @tparam OcmOutputShape The shape of the output tensor.
* @param ocmInput The input tensor.
* @param ocmOutput The output tensor.
* @param ocmMemAlloc ocm allocator to be used locally.
* @return void
*/
template <ResizeMethod resizeMethod = ResizeMethod::BILINEAR_INTERPOLATION,
CoordinateTransform coordinateTransform = CoordinateTransform::HALF_PIXEL,
NearestMode nearestMode = NearestMode::ROUND_PREFER_FLOOR,
IntRoundMethod intRoundMethod = IntRoundMethod::ROUND,
typename OcmAllocatorType = EmptyType,
typename OcmInputShape,
typename OcmOutputShape,
std::enable_if_t<resizeMethod != ResizeMethod::BILINEAR_INTERPOLATION_MULTISTEP &&
resizeMethod != ResizeMethod::NEAREST_NEIGHBORS &&
OcmInputShape::location == TensorLocation::OCM,
int> = 0>
INLINE void resize(OcmInputShape& ocmInput,
OcmOutputShape& ocmOutput,
const OcmAllocatorType& ocmMemAlloc = EmptyType()) {
With ResizeMethod::NEAREST_NEIGHBORS, a matching overload is selected automatically; it is identical except that coordinateTransform defaults to ASYMMETRIC.
Example:
OcmTensor<std::uint8_t, 1, 3, 224, 224> ocmIn;
OcmTensor<std::uint8_t, 1, 3, 112, 112> ocmOut;
ocmMem.allocate(ocmIn);
ocmMem.allocate(ocmOut);
memCpy(ddrIn, ocmIn);
image::resize<image::ResizeMethod::BILINEAR_INTERPOLATION, image::CoordinateTransform::HALF_PIXEL>(ocmIn, ocmOut);
memCpy(ocmOut, ddrOut);
DDR → DDR Resize
Resizes a DDR tensor of shape (batch, channels, height, width) into a DDR tensor of shape (batch, channels, resized_height, resized_width). Channels are streamed through a double-buffered OCM working set and resized on chip, so a single channel of input plus output must fit within reservedSize bytes of OCM (default: half of OCM). An OCM allocator is required.
/src/image.hppLines 2482–2515 /**
* @brief General purpose tensor resize for Ddr -> Ddr.
*
* Input tensor shape must be of form (batch, channels, height, width).
* Output tensor shape must be of form (batch, channels, resized_height, resized_width)
* @tparam resizeMethod Selection of resize method.
* @tparam coordinateTransform Selection of coordinate transform method.
* @tparam nearestMode Selection of internal rounding method. Only applicable for NEAREST_NEIGHBORS.
* @tparam reservedSize Amount of reserved ocm storage that can be used in this function.
* @tparam intRoundMode Selection for output int rounding method. Only applicable for BILINEAR_INTERPOLATION.
* @tparam multicoreMode Selection for multicore processing mode.
* @tparam numFracBits Number of fractional bits for fixed point bilinear operations.
* @tparam OcmAllocatorType Type of ocm allocator.
* @tparam DdrInputShape The Ddr region shape of the input tensor.
* @tparam DdrOutputShape The Ddr region shape of the output tensor.
* @param ddrInput The input tensor.
* @param ddrOutput The output tensor.
* @param ocmMemAlloc ocm allocator to be used locally.
* @return void
*/
template <ResizeMethod resizeMethod = ResizeMethod::BILINEAR_INTERPOLATION,
CoordinateTransform coordinateTransform = CoordinateTransform::HALF_PIXEL,
NearestMode nearestMode = NearestMode::ROUND_PREFER_FLOOR,
std::int32_t reservedSize = ocm::ocmSizeBytes / 2,
IntRoundMethod intRoundMethod = IntRoundMethod::ROUND,
MultiCoreMode multicoreMode = MultiCoreMode::Single,
typename OcmAllocatorType,
typename DdrInputShape,
typename DdrOutputShape,
std::enable_if_t<resizeMethod != ResizeMethod::BILINEAR_INTERPOLATION_MULTISTEP &&
resizeMethod != ResizeMethod::NEAREST_NEIGHBORS &&
DdrInputShape::location == TensorLocation::DDR,
int> = 0>
INLINE void resize(DdrInputShape& ddrInput, DdrOutputShape& ddrOutput, OcmAllocatorType& ocmMemAlloc) {
As with the OCM overload, ResizeMethod::NEAREST_NEIGHBORS selects a matching overload whose coordinateTransform defaults to ASYMMETRIC.
The DDR overloads also support multicore execution via the multicoreMode parameter. With MultiCoreMode::All, the batch * channels planes are divided evenly across the cores in the kernel group and each core resizes its share; a kGroupSync() is performed before returning. With MultiCoreMode::Single (the default), the calling core processes all channels.
Example (multicore, nearest neighbors):
MemAllocator ocmMem;
DdrInputShape ddrInput(ddrInputPtr);
DdrOutputShape ddrOutput(ddrOutputPtr);
image::resize<image::ResizeMethod::NEAREST_NEIGHBORS,
image::CoordinateTransform::HALF_PIXEL,
image::NearestMode::ROUND_PREFER_FLOOR,
ocm::ocmSizeBytes / 2,
image::IntRoundMethod::CAST,
MultiCoreMode::All>(ddrInput, ddrOutput, ocmMem);
Optimized Paths
The implementation selects an optimized kernel at compile time when the shapes and modes allow it (canOptimizeDownscale / canOptimizeUpscale in image_resize_helpers.hpp). No code changes are needed — the same resize call dispatches automatically.
| Path | Conditions |
|---|---|
| Optimized downscale | Bilinear + HALF_PIXEL, 1-byte element type (int8/uint8), each axis scaled by exactly 1×, 2×, or 4×. Uses packed flows instead of RAU gathers. |
| Optimized 2× upscale | 2× on both axes, 1-byte element type, bilinear + HALF_PIXEL or nearest neighbors with any transform except ALIGN_CORNERS. Streams tiles through flows and computes via neighbor exchange. |
| Optimized 4× upscale | 4× on both axes, 1-byte element type, bilinear + HALF_PIXEL, input larger than coreDim / 4 in at least one axis. |
| General | All other shape/type/mode combinations. Processes a row of output at a time, gathering the 4 source pixels per output pixel through RAU. |
The general bilinear path computes interpolation weights in fixed point (FixedPoint32<31>) and clamps source coordinates at image borders (border replication).
Related
For resizing 3-channel images with fused color conversion, see resizeImage in Image Transformations.
