В прошлой статье привел пример кода по созданию матриц armadillo из изображений, с помощью libjpeg-turbo.

Код внизу:

#include <iostream>
#include <armadillo>
#include <turbojpeg.h>
#include <jpeglib.h>
#include <chrono>
#include <opencv2/opencv.hpp>

using namespace arma;
using namespace std;
using namespace std::chrono;

struct jpeg_error_mgr jerr;
typedef unsigned short ushort;
typedef unsigned int uint;

int method1(char *jpegUrl) {
    auto start = high_resolution_clock::now();
    FILE *infile;
    struct jpeg_decompress_struct dinfo;
    JSAMPARRAY buffer = 0;

    dinfo.err = jpeg_std_error(&jerr);

    infile = fopen(jpegUrl, "rb");
    jpeg_create_decompress(&dinfo);
    jpeg_stdio_src(&dinfo, infile);
    jpeg_read_header(&dinfo, TRUE);
    jpeg_start_decompress(&dinfo);

    int width = dinfo.image_width;
    int height = dinfo.image_height;
    int color_num = dinfo.output_components;

    /* Make a one-row-high sample array that will go away when done with image */
    buffer = (*dinfo.mem->alloc_sarray)((j_common_ptr) &dinfo, JPOOL_IMAGE, width * color_num, 1);

    // rgb image
    int i = 0, j = 0, k1;
    short img_matR[height][width];
    short img_matG[height][width];
    short img_matB[height][width];

    while (dinfo.output_scanline < dinfo.output_height) {
        jpeg_read_scanlines(&dinfo, buffer, 1);
        for (j = 0; j < width; j++) {
            k1 = (j * 3);
            img_matR[i][j] = (short) buffer[0][k1 + 0];
            img_matG[i][j] = (short) buffer[0][k1 + 1];
            img_matB[i][j] = (short) buffer[0][k1 + 2];
        }
        i++;
    }

    Mat<short> img_r(*img_matR, height, width, false);
    Mat<short> img_g(*img_matG, height, width, false);
    Mat<short> img_b(*img_matB, height, width, false);

    jpeg_finish_decompress(&dinfo);
    jpeg_destroy_decompress(&dinfo);

    auto stop = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(stop - start);
    return duration.count();
}

int method2(char *jpegUrl) {
    auto start = high_resolution_clock::now();
    FILE *jpegFile = fopen(jpegUrl, "rb");
    unsigned char *jpegBuf = NULL, *imgBuf = NULL;
    uint jpegSize;
    int width, height, pixelFormat, size, s, c;

    fseek(jpegFile, 0, SEEK_END);
    size = ftell(jpegFile);
    fseek(jpegFile, 0, SEEK_SET);
    jpegSize = size;

    if ((jpegBuf = tjAlloc(jpegSize)) == NULL)
        cout << ("allocating JPEG buffer") << endl;
    if (fread(jpegBuf, jpegSize, 1, jpegFile) < 1)
        cout << ("reading input file") << endl;
    fclose(jpegFile);

    tjhandle jpegInstance = tjInitDecompress();
    tjDecompressHeader3(jpegInstance, jpegBuf, jpegSize, &width, &height, &s, &c);

    pixelFormat = TJPF_RGBX;
    int pix_size = tjPixelSize[pixelFormat]; // если  RGB, то 4 байта на пиксель (в libjpeg 3 байта), GRAYSCALE - 1 байт.

    imgBuf = tjAlloc(width * height * tjPixelSize[pixelFormat]);
    tjDecompress2(jpegInstance, jpegBuf, jpegSize, imgBuf, width, 0, height, pix_size, TJFLAG_FASTUPSAMPLE);

    short img_matR[height][width];
    short img_matG[height][width];
    short img_matB[height][width];
    int i, j, k1, k2, k3;
    for (i = 0; i < height; i++) {
        k1 = (i * width * pix_size);
        for (j = 0; j < width; j++) {
            k2 = (j * pix_size);
            k3 = k1 + k2;
            img_matR[i][j] = (short) imgBuf[k3 + 0];
            img_matG[i][j] = (short) imgBuf[k3 + 1];
            img_matB[i][j] = (short) imgBuf[k3 + 2];
        }
    }

    Mat<short> img_r(*img_matR, height, width, false, false);
    Mat<short> img_g(*img_matG, height, width, false, false);
    Mat<short> img_b(*img_matB, height, width, false, false);

//    Cube<short> img_cube(height, width, 3);
//    img_cube.slice(0) = img_r;
//    img_cube.slice(1) = img_g;
//    img_cube.slice(2) = img_b;

    tjFree(imgBuf);
    tjFree(jpegBuf);
    tjDestroy(jpegInstance);
    auto stop = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(stop - start);
    return duration.count();
}

int method3(char *jpegUrl) {
    auto start = high_resolution_clock::now();
    cv::Mat image = cv::imread(jpegUrl, 1);
    auto stop = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(stop - start);
    return duration.count();
}

int main(int argc, char **argv) {
    char *url = argv[1];
    auto t1 = method1(url);
    auto t2 = method2(url);
    auto t3 = method3(url);

    cout << "Time taken by libjpeg      : " << t1 << " microseconds" << endl;
    cout << "Time taken by libjpeg-turbo: " << t2 << " microseconds" << endl;
    cout << "Time taken by OpenCV       : " << t3 << " microseconds" << endl;

    float t2t1 = (float) t2 / t1;
    float t1t2 = (float) t1 / t2;
    float t3t2 = (float) t3 / t2;
    if (t1 > t2)
        printf("libjpeg-turbo faster than libjpeg in %.2f times \n", t1t2);
    if (t2 > t1)
        printf("libjpeg faster than libjpeg-turbo in %.2f times \n", t2t1);

    printf("libjpeg-turbo faster than OpenCV in %.2f times \n", t3t2);
    return 0;
}

Вывод программы, проверял на изображении RGB 1200x797 пикселей.

Time taken by libjpeg      : 17779 microseconds
Time taken by libjpeg-turbo: 14988 microseconds
Time taken by OpenCV       : 19820 microseconds
libjpeg-turbo faster than libjpeg in 1.19 times
libjpeg-turbo faster than OpenCV in 1.32 times

via GIPHY

Удачи!