假设图像中有一个像素 X ,值是 100 ,那么对这个X像素进行校正,步骤如下:
1. 归一化 :将像素值转换为 0 ~ 1 之间的实数。 算法如下 : ( x + 0. 5)/256 这里包含 1 个除法和 1 个加法操作。对于像素 X 而言 , 其对应的归一化值为 0. 392528 。
2. 预补偿 :根据公式 , 求出像素归一化后的 数据以 1 /gamma 为指数的对应值。这一步包含一个 求指数运算。若 gamma 值为 2. 2 , 则 1 /gamma 为 0. 454545 , 对归一化后的 X 值进行预补偿的结果就 是 0. 392528 ^0. 454545 = 0. 653764 。
3. 反归一化 :将经过预补偿的实数值反变换为 0 ~ 255 之间的整数值。具体算法为 : f * 256 - 0. 5 此步骤包含一个乘法和一个减法运算。续前 例 , 将 X 的预补偿结果 0. 653764 代入上式 , 得到 X 预补偿后对应的像素值为 167, 这个 167 就是最后送 入显示器的数据。
上诉运算效率比较低,针对这种情况,提出了一种快速查找表 (LUT:Look Up Table)算法。前提是转换前后,X的值在0~255之间。
本算法不适用于高Bit为转低Bit位 不适合,原理一样,估计公式不同?待研究
#include <math.h>
typedef unsigned char UNIT8; // 0~255
UNIT8 g_GammaLUT[256];
// fPrecompensation = 1 / gamma
void BuildLUTTable(float fPrecompensation )
{
int i;
float f;
for( i=0;i<256;i++)
{
f=(i+0.5F)/256;//归一化
f=(float)pow(f,fPrecompensation); //预补偿
g_GammaLUT[i]=(UNIT8)(f*256-0.5F);//反归一化 & 结果存入 g_GammaLUT
}
}
void GammaCorrectiom(UNIT8 src[],int iWidth,int iHeight,float fGamma,UNIT8 Dst[])
{
int iCols,iRows;
BuildLUTTable(1/fGamma);//gamma校正查找表初始化
//查找表矫正
for(iRows=0;iRows<iHeight;iRows++)
{
for(iCols=0;iCols<iWidth;iCols++)
{
Dst[iRows*iWidth+iCols]=g_GammaLUT[src[iRows*iWidth+iCols]];
}
}
}
typedef unsigned char UNIT8; // 0~255
UNIT8 g_GammaLUT[256];
// fPrecompensation = 1 / gamma
void BuildLUTTable(float fPrecompensation )
{
int i;
float f;
for( i=0;i<256;i++)
{
f=(i+0.5F)/256;//归一化
f=(float)pow(f,fPrecompensation); //预补偿
g_GammaLUT[i]=(UNIT8)(f*256-0.5F);//反归一化 & 结果存入 g_GammaLUT
}
}
void GammaCorrectiom(UNIT8 src[],int iWidth,int iHeight,float fGamma,UNIT8 Dst[])
{
int iCols,iRows;
BuildLUTTable(1/fGamma);//gamma校正查找表初始化
//查找表矫正
for(iRows=0;iRows<iHeight;iRows++)
{
for(iCols=0;iCols<iWidth;iCols++)
{
Dst[iRows*iWidth+iCols]=g_GammaLUT[src[iRows*iWidth+iCols]];
}
}
}