Log in

View Full Version : ColorYUV, Tweak, Levels


yaz
7th August 2003, 09:43
hi all !

i've seen that there's a new release availabe but i've not seen any note on these topics so i put my problems.

i use these functs extensively. (imho, most of the 'blocking problems' can be prevented this way.) so as to get closer to ColorYUV i tried to convert some of my older scripts using the equations given here&there(faq, manual, ...) surprisingly i found significant diffreneces in some instances. (i always checked the transformations with 'analyze') so i went on a more thorough investigation. here are some of my (re)quests occured

- tweak has a kinda 'auto-clamping' feature. i mean, if the transformation would lead outta ccir(tv) standard range, the values are clamped. a 0-255 clamping is essential with all filters affecting yuv values, but here i found a definite 'tv-scaling'. is it intentional, or does my system maulfunction?

- in the manual tweak is told to accept yuy2 only but it works with my yv12 clips. what's the case here?

- levels exhibits some more strange behav. levels(0,1,255,0,255) would do anything (according to the manual) but in fact, it does a 'pc->tv' scaling if the yuv values are outta tv scale. but levels(0,1,255,255,0) makes the 'photo-negative' wout clamping. can anyone explain it?

- afais, the manual entry of levels is that of ben's (ver1.01?), no word about yv12. does this function work properly with yv12 data?

- i can't check coloryuv transformations, cus i don't know how it calculates the new yuv values. (i've thought i knew, but i always get more or less different values than i expected) would anyone (sh0dan???) give me the exact form of the transformations? say, i'd be very greatful for a kinda y'=y(off,cont,gain,gamma) equation. if s'one would add the derivation of this params i'd be pleased for a lifetime:-) (pls, don't bother about complexity! i luv complex equations:-)

thx for any answ
y

sh0dan
7th August 2003, 10:01
You wanted it complex - you got it. "Kiraru2002(masani)" has written the original code.

It creates three lookuptables - one for each component.

Judge for yourself:

void Color::MakeGammaLUT(void)
{
static const int scale = 256, shift = 2^10,
coeff_y0 = 76309, coeff_y1 = 65536,
coeff_u0 = 132201, coeff_u1 = 116129,
coeff_v0 = 104597, coeff_v1 = 91881;
int i;
int val;
double g,b,c,gain;
double v;

y_thresh1 = u_thresh1 = v_thresh1 = -1;
y_thresh2 = u_thresh2 = v_thresh2 = 256;

gain = ((double)y_gain + scale) / scale;
c = ((double)y_contrast + scale) / scale;
b = ((double)y_bright + scale) / scale;
g = ((double)y_gamma + scale) / scale;
if (g < 0.01) g = 0.01;
for (i = 0; i < 256; i++)
{
val = i * shift;
switch (levels) {
case 1: // PC->TV
val = (int)((val - 16 * shift) * coeff_y0 / coeff_y1 + shift / 2);
break;
case 2: // TV->PC
case 3: // TV->PC.Y
val = (int)(val * coeff_y1 / coeff_y0 + 16 * shift + shift / 2);
break;
default: //none
break;
}
val = val / shift;

v = ((double)val) / 256;
v = (v * gain) + ((v-0.5) * c + 0.5) - v + (b - 1);

if (y_gamma != 0 && v > 0)
v = pow( v, 1 / g);
v = v * 256;

v += 0.5;
val = (int)floor(v);

if (val > 255)
val = 255;
else if (val < 0)
val = 0;

if (val > 235) {
if(y_thresh2 > 255) y_thresh2 = i;
if(opt) val = 235;
}
else if (val < 16) {
y_thresh1 = i;
if(opt) val = 16;
}
LUT_Y[i] = (unsigned char)val;
}

gain = ((double)u_gain + scale);
c = ((double)u_contrast + scale);
b = ((double)u_bright);
for (i = 0; i < 256; i++)
{
val = i * shift;
switch (levels) {
case 1: // PC->TV Scale
val = (int)((val - 128 * shift) * coeff_u0 / coeff_u1 + 128 * shift + shift / 2);
break;
case 2: // TV->PC Scale
val = (int)((val - 128 * shift) * coeff_u1 / coeff_u0 + 128 * shift + shift / 2);
break;
default: //none
break;
}
val = val / shift;

v = ((double)val);
v = (v * gain / scale) + ((v-128) * c / scale + 128) - v + b;

v += 0.5;
val = (int)floor(v);

if (val > 255)
val = 255;
else if (val < 0)
val = 0;

if (val > 240) {
if(u_thresh2 > 255) u_thresh2 = i;
if(opt) val = 240;
}
else if (val < 16) {
u_thresh1 = i;
if(opt) val = 16;
}
LUT_U[i] = (unsigned char)val;
}

gain = ((double)v_gain + scale);
c = ((double)v_contrast + scale);
b = ((double)v_bright);
for (i = 0; i < 256; i++)
{
val = i * shift;
switch (levels) {
case 1: // PC->TV Scale
val = (int)((val - 128 * shift) * coeff_v0 / coeff_v1 + 128 * shift + shift / 2);
break;
case 2: // TV->PC Scale
val = (int)((val - 128 * shift) * coeff_v1 / coeff_v0 + 128 * shift + shift / 2);
break;
default: //none
break;
}
val = val / shift;

v = ((double)val);
v = (v * gain / scale) + ((v-128) * c / scale + 128) - v + b;

v += 0.5;
val = (int)floor(v);

if (val > 255)
val = 255;
else if (val < 0)
val = 0;

if (val > 240) {
if(v_thresh2 > 255) v_thresh2 = i;
if(opt) val = 240;
}
else if (val < 16) {
v_thresh1 = i;
if(opt) val = 16;
}
LUT_V[i] = (unsigned char)val;
}
}

yaz
7th August 2003, 11:02
Originally posted by sh0dan
You wanted it complex - you got it. "Kiraru2002(masani)" has written the original code.
...

@sh0dan :-)))
it's okay, thx alot!

can u tell s'g about the other quests?

thx
y

Wilbert
7th August 2003, 11:57
@yaz,

Thanks for your tests! I will look at it and add it to the docs. Levels should work properly with YV12.