LUTs, 即Look up tables, 即查找表.
我刚开始接触LUTs查找表, 是在处理相机原始图片的时候. 我在前面已经提到过,
用log映射高于8位的数据, 得出的精度较好( 如果只是取高8位或是低8位, 那么还
要10位, 12位的数据做甚? 直接拿8位的数据还简单一些 ). 映射函数为:
f(in) = 2^( log(in) * 8 / 10 );
这个映射函数是, 将一个2^10次方的数据转换成2^8次方的数据, 即一个RGB的
最大值.
如果一张图片的像素为2050*2448, 那么, 就会有2050*2448个像素点, 我们进
行映射的时候, 就会进行2050*2448次log运算, 这个运算量相当大啊, 每拍一张照片
都要进行如何繁复的计算, 那将会令人崩溃. 所以要改进算法.
不过, 如果仔细观察, 会发现, 每个像素点的值的范围是0-1023( 2^10 - 1 = 1023).
这样, 如果我们把0-1023的log值都求出来, 在进行运算的时候, 我们只要去查找
已经运算出来的log值就行了. 如此, 我们只是把一堆log一直存放在内存中, 直到我们
手工去释放它们. 这个就是LUTs表, 事先将大运算量的数据计算出来, 当需要去取
的时候, 去查找LUTs表即可, LUTs表用数组表示最合适不过了.
所以, 写出来的代码可能如下( C语言 ):
代码
#include <math.h>
#define LUT_SIZE 1024
/*
* 映射函数
* floor是将小数点去掉, 因为 log1023 = 255.xxxx, 比255大, 所以将小数点去除
* log(in)/log(2), 因为C库函数中, 没有直接以2为底的对数函数, 根据对数性质, 可以用此来取代
*/
#define F(in) floor(pow(log(in)/log(2)*8/10))
unsigned char LUT[ LUT_SIZE ]; /* 定义LUT表 */
void BuildLookupTable( void );
#define Lookup(i) LUT[i] /* 使用宏定义, 如果使用函数, 会有函数开销, 返回值的传递也会有开销, 但它不检测边界 */
void BuildLookupTable( void )
{
int i;
for ( i = 0; i < LUT_SIZE; ++i ) {
LUT[i] = F(i);
}
}
#define LUT_SIZE 1024
/*
* 映射函数
* floor是将小数点去掉, 因为 log1023 = 255.xxxx, 比255大, 所以将小数点去除
* log(in)/log(2), 因为C库函数中, 没有直接以2为底的对数函数, 根据对数性质, 可以用此来取代
*/
#define F(in) floor(pow(log(in)/log(2)*8/10))
unsigned char LUT[ LUT_SIZE ]; /* 定义LUT表 */
void BuildLookupTable( void );
#define Lookup(i) LUT[i] /* 使用宏定义, 如果使用函数, 会有函数开销, 返回值的传递也会有开销, 但它不检测边界 */
void BuildLookupTable( void )
{
int i;
for ( i = 0; i < LUT_SIZE; ++i ) {
LUT[i] = F(i);
}
}