通过预处理器初始化3D查找表(LUT)?

时间:2016-11-06 12:38:37

标签: c++ qt image-processing c-preprocessor lookup-tables

我正在使用查找表来转换颜色空间和编码变体之间的原始像素数据。这是我的LUT的定义:

// loop through all possible values
for (int in_1 = 0; in_1 < 256; in_1++) {
    for (int in_2 = 0; in_2 < 256; in_2++) {
        for (int in_3 = 0; in_3 < 256; in_3++) {

            int out_1, out_2, out_3;

            // LUT YUV -> RGB
            // convert to rgb (http://softpixel.com/~cwright/programming/colorspace/yuv/)
            out_1 = (int)(in_1 + 1.4075 * (in_3 - 128));
            out_2 = (int)(in_1 - 0.3455 * (in_2 - 128) - (0.7169 * (in_3 - 128)));
            out_3 = (int)(in_1 + 1.7790 * (in_2 - 128));

            // clamp values
            if (out_1 < 0) { out_1 = 0; } else if (out_1 > 255) { out_1 = 255; }
            if (out_2 < 0) { out_2 = 0; } else if (out_2 > 255) { out_2 = 255; }
            if (out_3 < 0) { out_3 = 0; } else if (out_3 > 255) { out_3 = 255; }

            // set values in LUT
            LUTYUVTORGB[in_1][in_2][in_3].data[0] = (unsigned char)out_1;
            LUTYUVTORGB[in_1][in_2][in_3].data[1] = (unsigned char)out_2;
            LUTYUVTORGB[in_1][in_2][in_3].data[2] = (unsigned char)out_3;
        }
    }
}

它初始化如下:

for (int y = 0; y < h; y++) {
    for (int x = 0; x < w; x++) {
        xpos = (y*w + x); // don't calculate 3 times
        buff[x * 3 + 0] = psImage->comps[0].data[xpos];
        buff[x * 3 + 1] = psImage->comps[1].data[xpos];
        buff[x * 3 + 2] = psImage->comps[2].data[xpos];
    }
    memcpy(image.scanLine(y), buff, bytes_per_line);
}

然后应用LUT将原始像素数据复制到QImage():

await

LUT的值是静态的,每次程序启动时都必须初始化。有没有办法通过预处理器初始化它?或者将它保存在文件中是否值得推荐?

编辑:转换用于时间关键的视频应用程序,其中每个帧都必须单独处理。

非常感谢!

1 个答案:

答案 0 :(得分:-1)

我为这个表创建了一维数组,保存和加载这样的数组很方便。我认为在运行时使用这个数组不会降低性能。但我没有测试它的性能差异。

#include <stdio.h>
#include <stdlib.h>

#define LUTSIZE 0x1000000

typedef struct
{
    unsigned char data[3];
} rgb;

rgb *LUT;

inline int LUT_index(int in_1, int in_2, int in_3) {
    return in_1 * 0x10000 + in_2 * 0x100 + in_3 * 0x1;
}

inline rgb LUT_value(int in_1, int in_2, int in_3) {
    return LUT[LUT_index(in_1,in_2,in_3)];
}

void save(rgb *LUT, char* fileName) {

    FILE* file = fopen(fileName,"wb");
    int index;

    for (int in_1 = 0; in_1 < 256; in_1++) {
        for (int in_2 = 0; in_2 < 256; in_2++) {
            for (int in_3 = 0; in_3 < 256; in_3++) {

                int out_1, out_2, out_3;

                // LUT YUV -> RGB
                // convert to rgb (http://softpixel.com/~cwright/programming/colorspace/yuv/)
                out_1 = (int)(in_1 + 1.4075 * (in_3 - 128));
                out_2 = (int)(in_1 - 0.3455 * (in_2 - 128) - (0.7169 * (in_3 - 128)));
                out_3 = (int)(in_1 + 1.7790 * (in_2 - 128));

                // clamp values
                if (out_1 < 0) { out_1 = 0; } else if (out_1 > 255) { out_1 = 255; }
                if (out_2 < 0) { out_2 = 0; } else if (out_2 > 255) { out_2 = 255; }
                if (out_3 < 0) { out_3 = 0; } else if (out_3 > 255) { out_3 = 255; }

                index = LUT_index(in_1,in_2,in_3);

                // set values in LUT
                LUT[index].data[0] = (unsigned char)out_1;
                LUT[index].data[1] = (unsigned char)out_2;
                LUT[index].data[2] = (unsigned char)out_3;
            }
        }
    }

    fwrite((void*)LUT, sizeof(rgb),LUTSIZE,file);
    fclose(file);
}

void read(rgb *LUT, char* fileName) {
    FILE* file = fopen(fileName, "rb");
    fread((void*)LUT,sizeof(rgb),LUTSIZE,file);
    fclose(file);
}

int main(int argc, char *argv[])
{
    LUT = (rgb*)malloc(LUTSIZE * sizeof(rgb));
    save(LUT, "LUT_data");
    rgb testValue = LUT_value(5,3,7);
    printf("%d %d %d\n", testValue.data[0], testValue.data[1], testValue.data[2]);

    read(LUT, "LUT_data");
    testValue = LUT_value(5,3,7);
    printf("%d %d %d\n", testValue.data[0], testValue.data[1], testValue.data[2]);

    free(LUT);
}