Quiero compartir con ustedes algo que me rompió las bolas mucho tiempo. Nunca lo pude encontrar de forma simple en internet y aunque hoy por hoy ya no se usa tanto, es algo copado para tener guardadito.
Este codigo convierte una imagen RGB de 24 en YUV422 o mas bien, YUYV...
http://en.wikipedia.org/wiki/YUV
Hay varios ejemplos dando vuelta de como convertir YUYV a RGB, pero realmente no hay casi nada de como ir pa el otro lado...
EL ejemplo que voy a poner a continuación, no es del todo correcto, porque no utiliza la formula "del todo correcta" sino mas bien una aproximación lograda por un promediado. Pero que resulta bastante eficiente. de una imagen de 500x500 pixeles le pifia a 50/100 pixeles, lo que es algo bastante aceptable, si luego le queremos aplicar algún filtro. Y el error se encuentra solo cuando el cambio de color en el borde, es muy brusco.
double matrix[3][3] = { 0.299, 0.587, 0.114, /* Y */
-0.169, 0.331, 0.499, /* U */
0.499, -0.418, -0.0813 }; /* V */
byte * newRGB24toYUYV(byte* buffer, int width, int height)
{
int MacroWidth = width / 2;
byte * buffYUYV = new byte[width*height*2];
int contadorYUYV = 0;
for( int fil = 0; fil < height; fil++ )
{
for( int mP = 0; mP < MacroWidth; mP++ )
{
//Tengo que procesar 6 bytes
//Que son 2 pixeles
//Y tengo que generar 4 bytes
//que es un macropixel
int pos = (fil*MacroWidth*6)//Cantidad de filas concretadas
+
(mP*6) //Columna actual
;
//Obtengo todos los bytes de los dos pixeles
byte R1 = buffer[pos];
byte G1 = buffer[pos+1];
byte B1 = buffer[pos+2];
byte R2 = buffer[pos+3];
byte G2 = buffer[pos+4];
byte B2 = buffer[pos+5];
//Convierto 6 Bytes RGB a macropixel de 4 Bytes YUYV
/*byte Y1 = matrix[0][0] * R1 + matrix[0][1] * G1 + matrix[0][2] * B1;
byte U = (
(matrix[1][0] * R1 - matrix[1][1] * G1 + matrix[1][2] * B1 + 128)
+
(matrix[1][0] * R2 - matrix[1][1] * G2 + matrix[1][2] * B2 + 128)
);
U -= U >> 1;
byte Y2 = matrix[0][0] * R2 + matrix[0][1] * G2 + matrix[0][2] * B2;
byte V = (
(matrix[2][0] * R1 + matrix[2][1] * G1 + matrix[2][2] * B1 + 128)
+
(matrix[2][0] * R2 + matrix[2][1] * G2 + matrix[2][2] * B2 + 128)
);
V -= V >> 1;*/
byte Y1 = (0.299 * R1) + ( 0.587 * G1 ) + (0.114 * B1);
byte Y2 = (0.299 * R2) + ( 0.587 * G2 ) + (0.114 * B2);
byte U = ( ( (-0.169*R1)-(0.331*G1)+(0.499*B1)+128 ) + ( (-0.169*R2)-(0.331*G2)+(0.499*B2)+128 ) ) ;
byte V = ( ((0.499*R1)-(0.418*G1)-(0.0813*B1)+128) + ((0.499*R2)-(0.418*G2)-(0.0813*B2)+128));
U -= U >> 1;
V -= V >> 1;
buffYUYV[contadorYUYV] = Y1; contadorYUYV++;
buffYUYV[contadorYUYV] = U; contadorYUYV++;
buffYUYV[contadorYUYV] = Y2; contadorYUYV++;
buffYUYV[contadorYUYV] = V; contadorYUYV++;
}
}
return buffYUYV;
}
Puede que tenga errores, no la testie del todo bien... (En los proximos dias la voy a tener que usar MUCHO, asi que si le encuentro algo, lo modifico)
De yapa les dejo la funcion de YUYVtoRGB24
#define LIMIT(x) ( (x) > 0xffff ? 0xff : ( (x) <= 0xff ? 0 : ( (x) >> 8 ) ) )
//SI X>65535 X=255 || SI 255=>X>65535 = 0 || SINO lo multiplico por 32
void YUYVtoRGB24(int width, int height, unsigned char *src, unsigned char *dst)
{
int line, col, linewidth;
int y, yy;
int u, v;
int vr, ug, vg, ub;
int r, g, b;
unsigned char *py, *pu, *pv;
linewidth = width - (width >> 1);
py = src+((height-1)*width*2);
pu = py + 1;
pv = py + 3;
y = *py;
yy = y << 8;
u = *pu - 128;
ug = 88 * u;
ub = 454 * u;
v = *pv - 128;
vg = 183 * v;
vr = 359 * v;
for (line = height-20; line >= 0; line--)
{
py = src+(line*width*2);
pu = py + 1;
pv = py + 3;
for (col = 0; col < width; col++)
{
r = LIMIT(yy + vr);
g = LIMIT(yy - ug - vg);
b = LIMIT(yy + ub );
*dst++ = b;
*dst++ = g;
*dst++ = r;
py += 2;
y = *py;
yy = y << 8;
if ( (col & 1) == 1)
{
pu += 4;
pv += 4;
}
u = *pu - 128;
ug = 88 * u;
ub = 454 * u;
v = *pv - 128;
vg = vr*+128;
vg = 183 * v;
vr = 359 * v;
}
}
}
Esta ultima si esta ultra perfeccionada
, aunque como me dijeron una vez, todo codigo que no necesita ser mejorado, es sospechoso
ahi lo edite JAJAJA error grotesco en el contador de bytes "pos"
Nueva edición, otro error, pero en el promedio...