RGB в LAB и обратно ошибка

У меня возникли проблемы с преобразованием из RGB в LAB и обратно. Я пытаюсь поэкспериментировать с цветовым пространством LAB, но хочу убедиться, что смогу преобразовать его из RGB в XYZ в LAB и обратно.

Сначала все выглядело хорошо, но только если я использовал тестовое изображение Lena, как только я начал использовать другие изображения, я увидел, что синие и зеленые цвета были полностью отрезаны, и я не уверен, где именно ошибка.

Я проверял изображение с множеством цветов и после преобразования RGB в LAB и обратно я получил искаженные цвета.

Вот мой код:

{
double fcolorspace = 255.0f;

double* image1temp=new double[nWidth * nHeight * 4]; // this is our tempory buffer to hold image 1

// convert to RGB to LAB
for (int y = 0; y< nHeight; y++)
{
for (int x = 0; x< nWidth; x++)
{
int nIdx = x*4+y*4*nWidth;

double red1;
double green1;
double blue1;

double xyzX1;
double xyzY1;
double xyzZ1;

double var_X1;
double var_Y1;
double var_Z1;

double refX;
double refY;
double refZ;

double var_X11;
double var_Y12;
double var_Z13;

//read in image from array
red1   = double(pBGRA_in1[nIdx + CHANNEL_R]) / fcolorspace;
green1 = double(pBGRA_in1[nIdx + CHANNEL_G]) / fcolorspace;
blue1  = double(pBGRA_in1[nIdx + CHANNEL_B]) / fcolorspace;

//adjust gamma on image 1
if (red1 > 0.04045f)
{
red1 = powf((red1 + 0.055f) / 1.055f, 2.4f);
}
else
{
red1 = red1 / 12.92f;
}
if (green1 > 0.04045f)
{
green1 = powf((green1 + 0.055f) / 1.055f, 2.4f);
}
else
{
green1 = green1 / 12.92f;
}
if (blue1 > 0.04045f)
{
blue1 = powf((blue1 + 0.055f) / 1.055f, 2.4f);
}
else
{
blue1 = blue1 / 12.92f;
}

//scale
red1   = red1   * 100.0f;
green1 = green1 * 100.0f;
blue1  = blue1  * 100.0f;

//first we will convert the RGB image to XYZ
xyzX1 = (0.4124f * red1) + (0.3576f * green1) + (0.1805f * blue1);
xyzY1 = (0.2126f * red1) + (0.7152f * green1) + (0.0722f * blue1);
xyzZ1 = (0.0193f * red1) + (0.1192f * green1) + (0.9505f * blue1);

//reference white
refX = 95.047f; // Observer= 2°, Illuminant= D65
refY = 100.000f;
refZ = 108.883f;

//adjust LAB to reference white
var_X1 = xyzX1 / refX;
var_Y1 = xyzY1 / refY;
var_Z1 = xyzZ1 / refZ;

//LAB Conversion
if (var_X1 > 0.008856f)
{
var_X11 = powf(var_X1 , 1.0f/3.0f);
}
else
{
var_X11 = (7.787f * var_X1) + (16.0f/116.0f);
}

if (var_Y1 > 0.008856f)
{
var_Y12 = powf(var_Y1 , 1.0f/3.0f);
}
else
{
var_Y12 = (7.787f * var_Y1) + (16.0f/116.0f);
}

if (var_Z1 > 0.008856f)
{
var_Z13 = powf(var_Z1 , 1.0f/3.0f);
}
else
{
var_Z13 = (7.787f * var_Z1) + (16.0f/116.0f);
}

//adjust LAB scale
double cieL1 = (116.0f * var_Y12) - 16.0f;
double cieA1 = 500.0f * (var_X11 - var_Y12);
double cieB1 = 200.0f * (var_Y12 - var_Z13);

//we are now in the LAB colorspace
f_outred   = CLAMP255(cieL1);
f_outgreen = CLAMP255(cieA1);
f_outblue  = CLAMP255(cieB1);

//place LAB image in temp array
image1temp[nIdx + CHANNEL_R] = int(f_outred);
image1temp[nIdx + CHANNEL_G] = int(f_outgreen);
image1temp[nIdx + CHANNEL_B] = int(f_outblue);
}
}

//convert from LAB to XYZ
for (int x = 0; x< nWidth; x++)
{
for (int y = 0; y< nHeight; y++)
{
int nIdx = x * 4 + y * 4 * nWidth;

double refX;
double refY;
double refZ;

double var_X;
double var_Y;
double var_Z;

double cieX;
double cieY;
double cieZ;

double red;
double green;
double blue;

//reference white
refX = 95.047f; // Observer= 2°, Illuminant= D65
refY = 100.000f;
refZ = 108.883f;

double cieL = image1temp [nIdx + CHANNEL_R];
double cieA = image1temp [nIdx + CHANNEL_G];
double cieB = image1temp [nIdx + CHANNEL_B];

var_Y = (cieL + 16.0f) / 116.0f;
var_X = cieA / 500.0f + var_Y;
var_Z = var_Y - cieB / 200.0f;

if (powf(var_Y, 3.0f) > 0.008856)
{
var_Y = powf(var_Y, 3.0f);
}
else
{
var_Y = (var_Y - 16.0f / 116.0f) / 7.787f;
}
if (powf(var_X , 3.0f) > 0.008856f)
{
var_X = powf(var_X, 3.0f);
}
else
{
var_X = (var_X - 16.0f / 116.0f) / 7.787f;
}
if (powf(var_Z, 3.0f) > 0.008856)
{
var_Z = powf(var_Z, 3.0f);
}
else
{
var_Z = (var_Z - 16.0f / 116.0f) / 7.787f;
}

cieX = refX * var_X;
cieY = refY * var_Y;
cieZ = refZ * var_Z;

var_X = cieX / 100.0f;
var_Y = cieY / 100.0f;
var_Z = cieZ / 100.0f;

red   = var_X * 3.2406f  + var_Y * -1.5372f + var_Z * -0.4986f;
green = var_X * -0.9689f + var_Y * 1.8758f  + var_Z * 0.0415f;
blue  = var_X * 0.0557f  + var_Y * -0.2040f + var_Z * 1.0570f;

if (red > 0.0031308f)
{
red = 1.055f * powf(red , (1.0f / 2.4f)) - 0.055f;
}
else
{
red = 12.92f * red;
}
if (green > 0.0031308f)
{
green = 1.055f * powf(green , (1.0f / 2.4f)) - 0.055f;
}
else
{
green = 12.92f * green;
}
if (blue > 0.0031308f)
{
blue = 1.055f * powf(blue , (1.0f / 2.4f)) - 0.055f;
}
else
{
blue = 12.92f * blue;
}

red = CLAMP255(red * fcolorspace);
green = CLAMP255(green * fcolorspace);
blue = CLAMP255(blue * fcolorspace);

pBGRA_out[nIdx + CHANNEL_R] = red;
pBGRA_out[nIdx + CHANNEL_G] = green;
pBGRA_out[nIdx + CHANNEL_B] = blue;
}
}

delete [] image1temp;//delete the array
delete [] image2temp;//delete the array

}

0

Решение

Вы не показываете источник для CLAMP255, но я предполагаю, что он ограничивает значения от 0 до 255. Для вывода Lab это было бы совершенно неправильно, так как они используют другой диапазон; я знаю это a а также b опуститься ниже нуля.

1

Другие решения

Других решений пока нет …