ImageResizer C++ lib. Provides image resizing using SIMD-optimized bicubic interpolation

€200.00

We sell source code of this library as is, without future updates and technical support according to perpetual non-exclusive royalty-free license. You pay once and can use this library in your software and hardware products without limits. Please read the license agreement before purchasing: LICENSE.

We sell source code of this library as is, without future updates and technical support according to perpetual non-exclusive royalty-free license. You pay once and can use this library in your software and hardware products without limits. Please read the license agreement before purchasing: LICENSE.

Overview

ImageResizer C++ library provides image resizing with SIMD-optimized bicubic interpolation (Keys cubic, a = -0.75). The library implements a two-pass separable filter with platform-specific vectorization: SSSE3 + AVX2 on x86/x64, NEON on ARM64, and a scalar fallback for other architectures. Tile-based processing ensures L2 cache locality for upscale paths, while a row-cache strategy is used for downscale. The library supports multi-threaded row-level parallelism via OpenMP with automatic or user-defined thread count. Input data must be 3-byte-per-pixel interleaved format (BGR24, RGB24 and YUV24). The library uses C++17 standard.

Documentation

Documentation: GO TO DOCUMENATION

Simple interface

namespace cr
{
namespace video
{
/// Image resizer class.
class ImageResizer
{
public:

    /// Get the version of the ImageResizer class.
    static std::string getVersion();

    /// Resize image.
    bool resize(uint8_t* src, int srcWidth, int srcHeight,
                uint8_t* dst, int dstWidth, int dstHeight,
                int numThreads = 0);
};
}
}

Simple example

#include <iostream>
#include <cstdint>
#include <vector>
#include <chrono>
#include "ImageResizer.h"

using namespace std;
using namespace cr::video;
using namespace std::chrono;

int main(void)
{
    cout << "ImageResizer v" << ImageResizer::getVersion() << endl;

    // Source image size.
    const int srcWidth = 640;
    const int srcHeight = 512;

    // Destination image size.
    const int dstWidth = 1920;
    const int dstHeight = 1080;

    // Create source image with deterministic pattern.
    vector<uint8_t> srcImg(srcWidth * srcHeight * 3);
    for (int y = 0; y < srcHeight; ++y)
        for (int x = 0; x < srcWidth; ++x) {
            int idx = (y * srcWidth + x) * 3;
            srcImg[idx + 0] = (uint8_t)((x * 37 + y * 13) & 0xFF);
            srcImg[idx + 1] = (uint8_t)((x * 59 + y * 7)  & 0xFF);
            srcImg[idx + 2] = (uint8_t)((x * 23 + y * 41) & 0xFF);
        }

    // Create destination image buffer.
    vector<uint8_t> dstImg(dstWidth * dstHeight * 3);

    // Image resizer.
    ImageResizer imageResizer;

    // Resize image.
    auto begin = steady_clock::now();
    bool result = imageResizer.resize(srcImg.data(), srcWidth, srcHeight,
                                      dstImg.data(), dstWidth, dstHeight, 0);
    auto end = steady_clock::now();

    cout << "Result: " << (result ? "OK" : "FAIL") << endl;
    cout << "Resize time: " <<
    duration_cast<microseconds>(end - begin).count() << " us" << endl;

    return 0;
}