я вчера сумбурно выразился, сегодня постараюсь расшифровать, что имел ввиду.
читаем http://en.wikipedia.org/wiki/YUV
линейные перобразования там, матрица классическая, в старших классах школы проходили, поэтому в натуральных числах ограничений по преобразованиям нет никаких. фактически там поворот + масштабирование в трехмерной системе координат. на плоскости это выглядит примерно так
/\
----------- / \
| | / \
| | _\ / \
| | / \ /
| | \ /
----------- \ /
\/
а вот если мы придём от натуральных чисел к целым положительным, да еще и наложим это на видимые глазом цвета, тут и появятся все эти ограничения, которые вы именуете "широтой диапазона".
вот те хвостики, что у ромба сверху и снизу вылезают за диапазон(горизонтальные линии [0-255]) и отсекаются. это тот самый пересвет
для иллюстрации я программку написал, каждый может проверить своими глазами. в ней хорошо видно, что, хотя диапазоны сильно не совпадают, ни один из них нельзя назвать более узким, он просто другой.
программка в цикле преобразует цвета из rgb в yuv и переводит их в целое (диапазон НЕ РЕЖЕТ) очень интересные результаты наблюдаются.
для затравки приведу чуток вывода:
Rgb 0 0 0 -> yuv 0 111 157 Rgb 1 0 0 -> yuv 0 111 157 Rgb 2 0 0 -> yuv 1 111 158 Rgb 3 0 0 -> yuv 1 111 159 Rgb 4 0 0 -> yuv 1 111 159 Rgb 5 0 0 -> yuv 1 110 160 Rgb 6 0 0 -> yuv 2 110 161хорошо видно, что для фактически разных цветов RGB получаются одинаковые YUV. широтой диапазона как бы и не пахнет.
с другой стороны видим еще более интересные результаты:
rgb 70 384 23 <- Yuv 249 0 0 rgb 71 385 24 <- Yuv 250 0 0 rgb 72 386 25 <- Yuv 251 0 0 rgb 73 387 26 <- Yuv 252 0 0 rgb 74 388 27 <- Yuv 253 0 0 rgb 75 389 28 <- Yuv 254 0 0 rgb 76 390 29 <- Yuv 255 0 0вот он тот самый пересвет - из диапазона [0..255] зеленая компонента вылезла в полтора раза.
а ниже еще веселее
rgb 105 -10 -226 <- yuV 0 0 249 rgb 106 -10 -226 <- yuV 0 0 250 rgb 107 -11 -226 <- yuV 0 0 251 rgb 108 -11 -226 <- yuV 0 0 252 rgb 110 -12 -226 <- yuV 0 0 253 rgb 111 -13 -226 <- yuV 0 0 254 rgb 112 -13 -226 <- yuV 0 0 255тут мы уходим глубоко в область отрицательную....
теперь можно вспомнить и про зрение.
вот так накладывается rgb диапазон на то, что может увидеть человек.
Lab же, например, накладывается куда удачнее. и в этом преимущество этого цветового пространства.
но к математической широте диапазона это уже не имеет прямого отношения. и формулы там посложнее матриц.
надеюсь я, наконец, отделил
на закуску программа. выполняем в командной строке как cscript yuv.js > result.txt и наслаждаемся результатом в result.txt
function rgb2yuv(r,g,b) { var color = new Array(); color.r = r; color.g = g; color.b = b; // приводим RGB к диапазону [0..1] r = r/255; g=g/255; b=b/255; // R,G,B = [0..1] // Y = 0.299R + 0.587G + 0.114B // U = - 0.147R - 0.289G + 0.436B // V = 0.615R - 0.515G - 0.100B // Y = [0,1] U = [-0.436,0.436], V = [-0.615,0.615] var y = 0.299*r + 0.587*g + 0.114*b; var u = -0.147*r - 0.289*g + 0.436*b; var v = 0.615*r - 0.515*g - 0.100*b; // приводим YUV к диапазону [0.255] // именно здесь получается фигня - из-за округления! color.y = Math.round(y*255); color.u = Math.round((u+0.436)*255); color.v = Math.round((v+0.615)*255); return color; } function yuv2rgb(y,u,v) { var color = new Array(); color.y = y; color.u = u; color.v = v; // приводим YUV к их диапазону y = (y/255); u=(u/255)-0.436; v=(v/255)-0.615; //r = y + 1.13983*v //g = y -0.39465*u -0.58060*v //b = y + 2.03211*u var r = y + 1.13983*v var g = y - 0.39465*u - 0.58060*v var b = y + 2.03211*u // приводим RGB к диапазону [0.255] // именно здесь получается фигня - из-за округления! color.r = Math.round(r*255); color.g = Math.round(g*255); color.b = Math.round(b*255); return color; } function frm(a) { a = (' '+a.toString()); return a.substr(a.length-4,4); } function prn(txt, color) { txt = txt.replace(/\{1\}/,frm(color.r)).replace(/\{2\}/,frm(color.g)).replace(/\{3\}/,frm(color.b)).replace(/\{4\}/,frm(color.y)).replace(/\{5\}/,frm(color.u)).replace(/\{6\}/,frm(color.v)); WScript.StdOut.WriteLine(txt); } for (i = 0; i<256; i++ ) { prn('Rgb {1} {2} {3} -> yuv {4} {5} {6}', rgb2yuv(i,0,0)); } for (i = 0; i<256; i++ ) { prn('rGb {1} {2} {3} -> yuv {4} {5} {6}', rgb2yuv(0,i,0)); } for (i = 0; i<256; i++ ) { prn('rgB {1} {2} {3} -> yuv {4} {5} {6}', rgb2yuv(0,0,i)); } for (i = 0; i<256; i++ ) { prn('rgb {1} {2} {3} <- Yuv {4} {5} {6}', yuv2rgb(i,0,0)); } for (i = 0; i<256; i++ ) { prn('rgb {1} {2} {3} <- yUv {4} {5} {6}', yuv2rgb(0,i,0)); } for (i = 0; i<256; i++ ) { prn('rgb {1} {2} {3} <- yuV {4} {5} {6}', yuv2rgb(0,0,i)); } //контрольные преобразования - хорошо показывают ошибки округления prn('control RGB {1} {2} {3} <- yuv {4} {5} {6}', yuv2rgb(0,111,157)); prn('control RGB {1} {2} {3} <- yuv {4} {5} {6}', yuv2rgb(76,74,314)); prn('control RGB {1} {2} {3} <- yuv {4} {5} {6}', yuv2rgb(150,37,25)); prn('control RGB {1} {2} {3} <- yuv {4} {5} {6}', yuv2rgb(29,222,131)); prn('control rgb {1} {2} {3} -> YUV {4} {5} {6}', rgb2yuv(-179,135,-226)); prn('control rgb {1} {2} {3} -> YUV {4} {5} {6}', rgb2yuv(76,390,29)); prn('control rgb {1} {2} {3} -> YUV {4} {5} {6}', rgb2yuv(-179,34,292)); prn('control rgb {1} {2} {3} -> YUV {4} {5} {6}', rgb2yuv(112,-13,-226));
да, хотел и забыл про битность на наглядном примере пояснить.
есть у нас метровая резинка, отмечаем на ней сантиметровые деления. - это будет наша почти 10-битная зеленая шкала.
"преобразуем в YUV " - растягиваем резинку на два метра. "Диапазон увеличился!". естественно, резинка стала длинее. любой инструментальный мониторинг это покажет. однако теперь на этой резинке 35 см не отмеришь. и вообще любое нечетное число не отмеришь - нет соответствующих делений, они теперь через 2 сантиметра идут.