2016-11-06 6 views
0

Я использую таблицу поиска, чтобы преобразовывать необработанные пиксельные данные между цветовыми пространствами и вариантами кодирования. Это определение моего LUT:Инициализировать таблицу 3D-поиска (LUT) через препроцессор?

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

rgb LUTYUVTORGB[256][256][256]; 

Он инициализируется следующим образом:

// 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; 
     } 
    } 
} 

ТМП затем применяется для копирования исходных данных пикселя в QImage():

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 являются статическими и должны быть инициализированы каждый раз, когда запускается программа. Есть ли способ инициализировать его через препроцессор? Или было бы желательно сохранить его в файле?

EDIT: Преобразование используется в видеофрагменте, критическом по времени, где каждый кадр должен обрабатываться индивидуально.

Большое спасибо!

+1

Зачем вам нужен такой большой (64MiB) справочный стол в первую очередь? Преобразование достаточно простое, чтобы вы могли сделать это на лету. – Leon

+0

Моя рекомендация - сохранить его в файле с некоторой структурой. –

+0

@Leon Я должен был упомянуть, что преобразование используется в приложении с критичным временем видео, где каждый кадр должен обрабатываться индивидуально. – tlaloc

ответ

-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); 
}  
+2

Многомерный массив уже непрерывный в памяти, вам не нужно перерабатывать его, чтобы сделать его «сериализуемым». – dtech

+0

Спасибо @ddriver, я протестировал оба массива так же. –