I have copied this code from the internet, but it doesn't seem to work.
All it does is draw a red line on one edge of a black picture it makes.
I have been playing with it quite a long time and found that when I print the contents of r1, r2 and r3, it writes:
(0,0)
(0.866025,0)
(-0.866025,0)
So that seems like one thing, that it displays the parts of the complex number in the wrong order, but why does it display r1 to be zero, when it is clearly not?
Also, does it seem to be the cause of this code not working?
GLuint CMyApp::NewtonFractalTexture()
{
const int pic_size = 256;
unsigned char tex[pic_size][pic_size][3];
int MaxCount = 255;
int color_multiplier = 15;
float precision = 0.0001;
std::complex<double> r1 = (1, 0);
std::complex<double> r2 = (-0.5, sin(2 * PI / 3));
std::complex<double> r3 = (-0.5, -sin(2 * PI / 3));
std::cout << r1 << " " << r2 << " " << r3 << std::endl;
std::cout << abs(r1) << " " << abs(r2) << " " << abs(r3) << std::endl;
/*
std::complex<double> roots[birds_num];
for (int i = 0; i < birds_num; ++i){
roots[i] = (bird_positions[i][0], bird_positions[i][2]);
}
*/
for (int i = 0; i < pic_size; ++i){
for (int j = 0; j < pic_size; ++j)
{
//
std::complex<double> z = (i, j);
//
int count = 0;
while (count < MaxCount && abs(z - r1) >= precision && abs(z - r2) >= precision && abs(z - r3) >= precision){
/*
std::complex<double> my_numerator = (z - roots[0])*(z - roots[1])*(z - roots[2])*(z - roots[3])*(z - roots[4])*(z - roots[5])*(z - roots[6])*(z - roots[7])*(z - roots[8]);
std::complex<double> my_denominator = (z - roots[0])*(z - roots[0])*(z - roots[1])*(z - roots[2])*(z - roots[3])*(z - roots[4])*(z - roots[5])*(z - roots[6])*(z - roots[7])*(z - roots[8]) +
(z - roots[0])*(z - roots[1])*(z - roots[1])*(z - roots[2])*(z - roots[3])*(z - roots[4])*(z - roots[5])*(z - roots[6])*(z - roots[7])*(z - roots[8]) +
(z - roots[0])*(z - roots[1])*(z - roots[2])*(z - roots[2])*(z - roots[3])*(z - roots[4])*(z - roots[5])*(z - roots[6])*(z - roots[7])*(z - roots[8]) +
(z - roots[0])*(z - roots[1])*(z - roots[2])*(z - roots[3])*(z - roots[3])*(z - roots[4])*(z - roots[5])*(z - roots[6])*(z - roots[7])*(z - roots[8]) +
(z - roots[0])*(z - roots[1])*(z - roots[2])*(z - roots[3])*(z - roots[4])*(z - roots[4])*(z - roots[5])*(z - roots[6])*(z - roots[7])*(z - roots[8]) +
(z - roots[0])*(z - roots[1])*(z - roots[2])*(z - roots[3])*(z - roots[4])*(z - roots[5])*(z - roots[5])*(z - roots[6])*(z - roots[7])*(z - roots[8]) +
(z - roots[0])*(z - roots[1])*(z - roots[2])*(z - roots[3])*(z - roots[4])*(z - roots[5])*(z - roots[6])*(z - roots[6])*(z - roots[7])*(z - roots[8]) +
(z - roots[0])*(z - roots[1])*(z - roots[2])*(z - roots[3])*(z - roots[4])*(z - roots[5])*(z - roots[6])*(z - roots[7])*(z - roots[7])*(z - roots[8]) +
(z - roots[0])*(z - roots[1])*(z - roots[2])*(z - roots[3])*(z - roots[4])*(z - roots[5])*(z - roots[6])*(z - roots[7])*(z - roots[8])*(z - roots[8]);
*/
std::complex<double> my_numerator = z*z*z - 1.0;
std::complex<double> my_denominator = z*z * 3.0;
if (abs(z) > 0){
z = z - my_numerator / my_denominator;
}
++count;
}
//
tex[i][j][0] = 0;
tex[i][j][1] = 0;
tex[i][j][2] = 0;
//
if (abs(z - r1) < precision){
tex[i][j][0] = 255 - count * color_multiplier;
}
if (abs(z - r2) <= precision){
tex[i][j][1] = 255 - count * color_multiplier;
}
if (abs(z - r3) <= precision){
tex[i][j][2] = 255 - count * color_multiplier;
}
//
}
}
GLuint tmpID;
// generáljunk egy textúra erőforrás nevet
glGenTextures(1, &tmpID);
// aktiváljuk a most generált nevű textúrát
glBindTexture(GL_TEXTURE_2D, tmpID);
// töltsük fel adatokkal az...
gluBuild2DMipmaps( GL_TEXTURE_2D, // aktív 2D textúrát
GL_RGB8, // a vörös, zöld és kék csatornákat 8-8 biten tárolja a textúra
pic_size, pic_size, // kép méretének megadása
GL_RGB, // a textúra forrása RGB értékeket tárol, ilyen sorrendben
GL_UNSIGNED_BYTE, // egy-egy színkopmonenst egy unsigned byte-ról kell olvasni
tex); // és a textúra adatait a rendszermemória ezen szegletéből töltsük fel
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // bilineáris szűrés kicsinyítéskor
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // és nagyításkor is
glBindTexture(GL_TEXTURE_2D, 0);
return tmpID;
}
You're not initializing your complex numbers right. You either need to use
std::complex<double> r1(1, 0);
or
std::complex<double> r1 {1, 0};
(note the curly brackets here).
r1(1,0) is a constructor call, r1{1,0} is uniform initialization, and r1 = (1,0) is the same as r1 = 0 because the (1,0) is a use of the comma operator, whose value is the last expression.
Related
I have the following code:
u_ini = 0.1
v_ini = 0.1
z_ini = 0.1 # 初始化三个拉格朗日乘子
q = 0
lis = list(range(2))
u = list(sp.symbols('u:{}'.format(len(lis))))
v = list(sp.symbols('v:{}'.format(len(lis))))
z = sp.symbols('z')
p = list(sp.symbols('p:{}'.format(len(lis))))
lag1 = 0
lag2 = 0
lag3 = 0
p_symbol_sum = np.sum(p)
for i in range(k):
if i < k-1:
lag1 += B*ts_ratio[i]*sp.log(1+g[i]*p[i]/(sgm_2+g[i]*np.sum(p[i+1:k])),2)-q*(af_eff*p[i]+Pc-eh_eff*(1-ts_ratio[i])*g[i]*p_symbol_sum)
lag2 -= u[i] * (R_min - ts_ratio[i] * B * sp.log(1 + g[i] * p[i] / (sgm_2 + g[i] * np.sum(p[i + 1:k])),2))
elif i == k-1:
lag1 += B*ts_ratio[i]*sp.log(1+g[i]*p[i]/(sgm_2+g[i]*p[i]),2)-q*(af_eff*p[i]+Pc-eh_eff*(1-ts_ratio[i])*g[i]*p_symbol_sum)
lag2 -= u[i] * (R_min - ts_ratio[i] * B * sp.log(1+g[i]*p[i]/(sgm_2+g[i]*p[i]),2))
lag3 -= v[i] * (E_min - (1 - ts_ratio[i])*eh_eff*g[i]*p_symbol_sum) + z * (p[i] - p_max)
lag_fun = lag1 + lag2 + lag3
print("lag_fun:",lag_fun)
for i in range(k):
lag_fun.subs([(u[i],u_ini), (v[i],v_ini), (z,z_ini), (p[i],p_ini)]).evalf()
print("lag_fun:",lag_fun)
Why does the value of the expression not change after I count down the subs of the second line。
This is the output of the program. The first line is the output before using subs. The second is the output after using subs. Why hasn't it changed?
lag_fun: -u0*(-0.5*log(0.0410609879149758*p0/(0.0410609879149758*p1 + 0.001) + 1)/log(2) + 2) - u1*(-0.5*log(0.0123909311217172*p1/(0.0123909311217172*p1 + 0.001) + 1)/log(2) + 2) - v0*(-0.00205304939574879*p0 - 0.00205304939574879*p1 + 0.2) - v1*(-0.000619546556085859*p0 - 0.000619546556085859*p1 + 0.2) - z*(p0 - 20) - z*(p1 - 20) + 0.5*log(0.0410609879149758*p0/(0.0410609879149758*p1 + 0.001) + 1)/log(2) + 0.5*log(0.0123909311217172*p1/(0.0123909311217172*p1 + 0.001) + 1)/log(2)
lag_fun: -u0*(-0.5*log(0.0410609879149758*p0/(0.0410609879149758*p1 + 0.001) + 1)/log(2) + 2) - u1*(-0.5*log(0.0123909311217172*p1/(0.0123909311217172*p1 + 0.001) + 1)/log(2) + 2) - v0*(-0.00205304939574879*p0 - 0.00205304939574879*p1 + 0.2) - v1*(-0.000619546556085859*p0 - 0.000619546556085859*p1 + 0.2) - z*(p0 - 20) - z*(p1 - 20) + 0.5*log(0.0410609879149758*p0/(0.0410609879149758*p1 + 0.001) + 1)/log(2) + 0.5*log(0.0123909311217172*p1/(0.0123909311217172*p1 + 0.001) + 1)/log(2)
subs doesn't change anything in place, you have to capture the result for the same reason that this loop fails to change x:
>>> x = 0
>>> for i in range(10): x + 1
>>> x
0
So it must be
lag_fun = lag_fun.subs(etc...)
My function getHeightOfTerrain() is calling a barycentric formula function that is not returning the correct height for the one set test height in : heightMapFromArray[][].
I've tried watching OpenGL JAVA Game tutorials 14,21, 22, by "thin matrix" and I am confused on how to use my array: heightMapforBaryCentric in both of the supplied functions, and how to set the arguments that are passed to the baryCentic() function in some sort of manner so that I can solve the problem.
int creaateTerrain(int height, int width)
{
float holderY[6] = { 0.f ,0.f,0.f,0.f,0.f,0.f };
float scaleit = 1.5f;
float holder[6] = { 0.f,0.f,0.f,0.f,0.f,0.f };
for (int z = 0, z2 =0; z < iterationofHeightMap;z2++)
{
//each loop is two iterations and creates one quad (two triangles)
//however because each iteration is by two (i.e. : x=x+2) om bottom
//the amount of triangles is half the x value
//
//number of vertices : 80 x 80 x 6.
//column
for (int x = 0, x2 = 0; x < iterationofHeightMap;x2++)
{
//relevant - A : first triangle - on left triangle
//[row] [colum[]
holder[0] = heightMapFromArray[z][x];
//holder[0] = (float)imageData[(z / 2 * MAP_Z + (x / 2)) * 3];
//holder[0] = holder[0] / 255;// *scaleit;
vertices.push_back(glm::vec3(x, holder[0], z));
//match height map with online barycentric use
heightMapforBaryCentric[x2][z2] = holder[0];
holder[1] = heightMapFromArray[z+2][x];
//holder[1] = (float)imageData[(((z + 2) / 2 * MAP_Z + ((x) / 2))) * 3];
//holder[1] = holder[1] / 255;// 6 * scaleit;
vertices.push_back(glm::vec3(x, holder[1], z + 2));
//match height map with online barycentric use
heightMapforBaryCentric[x2][z2+1] = holder[1];
holder[2] = heightMapFromArray[z+2][x+2];
//holder[2] = (float)imageData[(((z + 2) / 2 * MAP_Z + ((x + 2) / 2))) * 3];
//holder[2] = holder[2] / 255;// *scaleit;
vertices.push_back(glm::vec3(x + 2, holder[2], z + 2));
////match height map with online barycentric use
heightMapforBaryCentric[x2+1][z2+1] = holder[2];
//relevant - B - second triangle (on right side)
holder[3] = heightMapFromArray[z][x];
//holder[3] = (float)imageData[((z / 2)*MAP_Z + (x / 2)) * 3];
//holder[3] = holder[3] / 255;// 256 * scaleit;
vertices.push_back(glm::vec3(x, holder[3], z));
holder[4] = heightMapFromArray[x+2][z+2];
//holder[4] = (float)imageData[(((z + 2) / 2 * MAP_Z + ((x + 2) / 2))) * 3];
//holder[4] = holder[4] / 255;// *scaleit;
vertices.push_back(glm::vec3(x + 2, holder[4], z + 2));
holder[5] = heightMapFromArray[x+2][z];
//holder[5] = (float)imageData[((z / 2)*MAP_Z + ((x + 2) / 2)) * 3];
//holder[5] = holder[5] / 255;// *scaleit;
vertices.push_back(glm::vec3(x + 2, holder[5], z));
x = x + 2;
}
z = z + 2;
}
return(1);
}
float getHeightOfTerrain(float worldX, float worldZ) {
float terrainX = worldX;
float terrainZ = worldZ;
int gridSquareSize = 2.0f;
gridX = (int)floor(terrainX / gridSquareSize);
gridZ = (int)floor(terrainZ / gridSquareSize);
xCoord = ((float)(fmod(terrainX, gridSquareSize)) / (float)gridSquareSize);
zCoord = ((float)(fmod(terrainZ, gridSquareSize)) / (float)gridSquareSize);
if (xCoord <= (1 - zCoord))
{
answer = baryCentric(
//left triangle
glm::vec3(0.0f, heightMapforBaryCentric[gridX][gridZ], 0.0f),
glm::vec3(0.0f, heightMapforBaryCentric[gridX][gridZ+1], 1.0f),
glm::vec3(1.0f, heightMapforBaryCentric[gridX+1][gridZ+1], 1.0f),
glm::vec2(xCoord, zCoord));
// if (answer != 1)
// {
// fprintf(stderr, "Z:gridx: %d gridz: %d answer: %f\n", gridX, gridZ,answer);
//
// }
}
else
{
//right triangle
answer = baryCentric(glm::vec3(0, heightMapforBaryCentric[gridX][gridZ], 0),
glm::vec3(1,heightMapforBaryCentric[gridX+1][gridZ+1], 1),
glm::vec3(1,heightMapforBaryCentric[gridX+1][gridZ], 0),
glm::vec2(xCoord, zCoord));
}
if (answer == 1)
{
answer = 0;
}
//answer = abs(answer - 1);
return(answer);
}
float baryCentric(glm::vec3 p1, glm::vec3 p2, glm::vec3 p3 , glm::vec2 pos) {
float det = (p2.z - p3.z) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.z - p3.z);
float l1 = ((p2.z - p3.z) * (pos.x - p3.x) + (p3.x - p2.x) * (pos.y - p3.z)) / det;
float l2 = ((p3.z - p1.z) * (pos.x - p3.x) + (p1.x - p3.x) * (pos.y - p3.z)) / det;
float l3 = 1.0f - l1 - l2;
return (l1 * p1.y + l2 * p2.y + l3 * p3.y);
}
My expected results were that the center of the test grid's height to be the set value .5 and gradually less as the heights declined. My results were the heights being all the same, varied, or increasing. Usually these heights were under the value of one.
What I try to achieve is to rotate a line around rectangle center so it always stays in its bounds touching them (or having some padding).
Now I have the following routine for this, as you see I use tan calculations dividing my rectangle into 8 parts (red lines)
It works so far, but for some reason I have inconsistency using other calculation for radius drawing (green line), the lines won't always match as expected and I wonder why.
Basically the same could be achieved using just sin/cos calculations and finding cross points between lines and rect borders, but for some reason I could not get it to work.
std::pair<Point, Point>
MathUtils::calculateRotatingLine(Size size, double degrees)
{
auto width = size.width;
auto height = size.height;
double diagonalAngleTopRight = radiansToDegrees(atan((width / 2) / (height / 2)));
double diagonalAngleBottomRight = 90 + (90 - diagonalAngleTopRight);
double diagonalAngleBottomLeft = 180 + diagonalAngleTopRight;
double diagonalAngleTopLeft = 180 + diagonalAngleBottomRight;
double x, y;
/*
* *8*1*
* 7* *2
* 6* *3
* *5*4*
*/
// 1
if (degrees >= 0 && degrees <= diagonalAngleTopRight) {
x = width / 2 + height / 2 * tan(degreesToRadians(degrees));
y = 0;
}
// 2
else if (degrees > diagonalAngleTopRight && degrees <= 90) {
x = width;
y = width / 2 * tan(degreesToRadians(degrees - diagonalAngleTopRight));
}
// 3
else if (degrees > 90 && degrees <= diagonalAngleBottomRight) {
x = width;
y = height / 2 + width / 2 * tan(degreesToRadians(degrees - 90));
}
// 4
else if (degrees > diagonalAngleBottomRight && degrees <= 180) {
x = width - height / 2 * tan(degreesToRadians(degrees - diagonalAngleBottomRight));
y = height;
}
// 5
else if (degrees > 180 && degrees <= diagonalAngleBottomLeft) {
x = width / 2 - height / 2 * tan(degreesToRadians(degrees - 180));
y = height;
}
// 6
else if (degrees > diagonalAngleBottomLeft && degrees <= 270) {
x = 0;
y = height - width / 2 * tan(degreesToRadians(degrees - diagonalAngleBottomLeft));
}
// 7
else if (degrees > 270 && degrees <= diagonalAngleTopLeft) {
x = 0;
y = height / 2 - width / 2 * tan(degreesToRadians(degrees - 270));
}
// 8
else {
x = height / 2 * tan(degreesToRadians(degrees - diagonalAngleTopLeft));
y = 0;
}
return {Point{width / 2, height / 2}, Point{x, y}};
}
Green line calculation
Point
MathUtils::calculateCirclePoint(double radius, double degrees)
{
return {radius * cos(degreesToRadians(degrees)), radius * sin(degreesToRadians(degrees))};
}
EDIT
Awesome, it works thanks to #MBo
Point
MathUtils::calculateCrossPoint(Size size, double degrees)
{
auto x0 = size.width / 2;
auto y0 = size.height / 2;
auto vx = cos(degreesToRadians(degrees - 90));
auto vy = sin(degreesToRadians(degrees - 90));
//potential border positions
auto ex = vx > 0 ? size.width : 0;
auto ey = vy > 0 ? size.height : 0;
//check for horizontal/vertical directions
if (vx == 0) {
return {x0, ey};
}
if (vy == 0) {
return {ex, y0};
}
// in general case find times of intersections with horizontal and vertical edge line
auto tx = (ex - x0) / vx;
auto ty = (ey - y0) / vy;
// and get intersection for smaller parameter value
if (tx <= ty) {
return {ex, y0 + tx * vy};
}
return {x0 + ty * vx, ey};
}
Pseudocode to find intersection of ray emitted from rectangle center (with angle an in radians) with edges. (Works also for other (x0,y0) positions)
x0 = width / 2;
y0 = height / 2;
vx = cos(an);
vy = sin(an);
//potential border positions
ex = vx > 0? width: 0
ey = vy > 0? height: 0
//check for horizontal/vertical directions
if vx = 0 then
return cx = x0, cy = ey
if vy = 0 then
return cx = ex, cy = y0
//in general case find times of intersections with horizontal and vertical edge line
tx = (ex - x0) / vx
ty = (ey - y0) / vy
//and get intersection for smaller parameter value
if tx <= ty then
return cx = ex, cy = y0 + tx * vy
else
return cx = x0 + ty * vx, cy = ey
I just tried implemting this filter using cimg but keep getting a seg fault. I am not sure why this is happening as the other filters that I have been using do not have that issue. Is there anything obvious that I am missing here?
CImg<float> gaussianBlur(CImg<float> source)
{
double frame[25];
double mean = 0;
int width = source.width;
int height = source.height;
CImg<float> destination;
destination = source;
for (int x = 1; x < int(width) - 3; x++)
{
for (int y = 1; y < int(height) - 3; y++)
{
mean = 0.0;
frame[0] = int(source(x - 2 ,y - 2)) * .003765;
frame[1] = int(source(x - 1 ,y - 2)) * .015019;
frame[2] = int(source(x - 0 ,y - 2)) * .023792;
frame[3] = int(source(x + 1 ,y - 2)) * .015019;
frame[4] = int(source(x + 2 ,y - 2)) * .003765;
frame[5] = int(source(x - 2 ,y - 1)) * .015019;
frame[6] = int(source(x - 1 ,y - 1)) * .059912;
frame[7] = int(source(x - 0 ,y - 1)) * .094907;
frame[8] = int(source(x + 1 ,y - 1)) * .059912;
frame[9] = int(source(x + 2 ,y - 1)) * .015019;
frame[10] = int(source(x - 2 ,y - 0)) * .023792;
frame[11] = int(source(x - 1 ,y - 0)) * .094907;
frame[12] = int(source(x - 0 ,y - 0)) * .150342;
frame[13] = int(source(x + 1 ,y - 0)) * .094907;
frame[14] = int(source(x + 2 ,y - 0)) * .023792;
frame[15] = int(source(x - 2 ,y + 1)) * .015019;
frame[16] = int(source(x - 1 ,y + 1)) * .059912;
frame[17] = int(source(x - 0 ,y + 1)) * .094907;
frame[18] = int(source(x + 1 ,y + 1)) * .059912;
frame[19] = int(source(x + 2 ,y + 1)) * .015019;
frame[20] = int(source(x - 2 ,y + 2)) * .003765;
frame[21] = int(source(x - 1 ,y + 2)) * .015019;
frame[22] = int(source(x - 0 ,y + 2)) * .023792;
frame[23] = int(source(x + 1 ,y + 2)) * .015019;
frame[24] = int(source(x + 2 ,y + 2)) * .003765;
for (int z = 0; z < 25; z++)
{
mean += frame[z];
}
destination(x,y) = float(mean / 25);
}
}
return destination;
}
for (int y = 1; y < int(height) - 3; y++)
{
mean = 0.0;
frame[0] = int(source(x - 2 ,y - 2)) * .003765;
When y == 1 you have y - 2 == -1, so you have an out-of-bounds access to the source image.
I've been trying to tackle a YUV422 into a RGB conversion problem for about a week. I've visited many different websites and have gotten different formulas from each one. If anyone else has any suggestions I would be glad to hear about them. The formulas below give me an image with either and overall purple or a green hue in them. As of this moment I haven't been able to find a formula that allows me to get back a proper RGB image. I have include all my various chunks of code below.
//for(int i = 0; i < 1280 * 720 * 3; i=i+3)
//{
// /*m_RGB->imageData[i] = pData[i] + pData[i+2]*((1 - 0.299)/0.615);
// m_RGB->imageData[i+1] = pData[i] - pData[i+1]*((0.114*(1-0.114))/(0.436*0.587)) - pData[i+2]*((0.299*(1 - 0.299))/(0.615*0.587));
// m_RGB->imageData[i+2] = pData[i] + pData[i+1]*((1 - 0.114)/0.436);*/
// m_RGB->imageData[i] = pData[i] + 1.403 * (pData[i+1] - 128);
// m_RGB->imageData[i+1] = pData[i] + 0.344 * (pData[i+1] - 128) - 0.714 * (pData[i+2] - 128);
// m_RGB->imageData[i+2] = pData[i] + 1.773 * (pData[i+2] - 128);
//}
for(int i = 0, j=0; i < 1280 * 720 * 3; i+=6, j+=4)
{
/*m_RGB->imageData[i] = pData[j] + pData[j+3]*((1 - 0.299)/0.615);
m_RGB->imageData[i+1] = pData[j] - pData[j+1]*((0.114*(1-0.114))/(0.436*0.587)) - pData[j+3]*((0.299*(1 - 0.299))/(0.615*0.587));
m_RGB->imageData[i+2] = pData[j] + pData[j+1]*((1 - 0.114)/0.436);
m_RGB->imageData[i+3] = pData[j+2] + pData[j+3]*((1 - 0.299)/0.615);
m_RGB->imageData[i+4] = pData[j+2] - pData[j+1]*((0.114*(1-0.114))/(0.436*0.587)) - pData[j+3]*((0.299*(1 - 0.299))/(0.615*0.587));
m_RGB->imageData[i+5] = pData[j+2] + pData[j+1]*((1 - 0.114)/0.436);*/
/*m_RGB->imageData[i] = pData[j] + 1.403 * (pData[j+3] - 128);
m_RGB->imageData[i+1] = pData[j] + 0.344 * (pData[j+1] - 128) - 0.714 * (pData[j+3] - 128);
m_RGB->imageData[i+2] = pData[j] + 1.773 * (pData[j+1] - 128);
m_RGB->imageData[i+3] = pData[j+2] + 1.403 * (pData[j+3] - 128);
m_RGB->imageData[i+4] = pData[j+2] + 0.344 * (pData[j+1] - 128) - 0.714 * (pData[j+3] - 128);
m_RGB->imageData[i+5] = pData[j+2] + 1.773 * (pData[j+1] - 128);*/
BYTE Cr = pData[j+3] - 128;
BYTE Cb = pData[j+1] - 128;
/*m_RGB->imageData[i] = pData[j] + Cr + (Cr >> 2) + (Cr >> 3) + (Cr >> 5);
m_RGB->imageData[i+1] = pData[j] - ((Cb >> 2) + (Cb >> 4) + (Cb >> 5)) - ((Cr >> 1) + (Cr >> 3) + (Cr >> 4) + (Cr >> 5));
m_RGB->imageData[i+2] = pData[j] + Cb + (Cb >> 1) + (Cb >> 2) + (Cb >> 6);
m_RGB->imageData[i+3] = pData[j+2] + Cr + (Cr >> 2) + (Cr >> 3) + (Cr >> 5);
m_RGB->imageData[i+4] = pData[j+2] - ((Cb >> 2) + (Cb >> 4) + (Cb >> 5)) - ((Cr >> 1) + (Cr >> 3) + (Cr >> 4) + (Cr >> 5));
m_RGB->imageData[i+5] = pData[j+2] + Cb + (Cb >> 1) + (Cb >> 2) + (Cb >> 6);*/
/*int R1 = clamp(1 * pData[j] + 0 * Cb + 1.4 * Cr, 0, 255), R2 = clamp(1 * pData[j+2] + 0 * Cb + 1.4 * Cr, 0, 255);
int G1 = clamp(1 * pData[j] - 0.343 * Cb - 0.711 * Cr, 0, 255), G2 = clamp(1 * pData[j+2] - 0.343 * Cb - 0.711 * Cr, 0, 255);
int B1 = clamp(1 * pData[j] + 1.765 * Cb + 0 * Cr, 0, 255), B2 = clamp(1 * pData[j+2] + 1.765 * Cb + 0 * Cr, 0, 255);*/
/*int R1 = clamp(pData[j] + 1.403 * (pData[j+3] - 128), 0, 255), R2 = clamp(pData[j+2] + 1.403 * (pData[j+3] - 128), 0, 255);
int G1 = clamp(pData[j] + 0.344 * (pData[j+1] - 128) - 0.714 * (pData[j+3] - 128), 0, 255), G2 = clamp(pData[j+2] + 0.344 * (pData[j+1] - 128) - 0.714 * (pData[j+3] - 128), 0, 255);
int B1 = clamp(pData[j] + 1.773 * (pData[j+1] - 128), 0, 255), B2 = clamp(pData[j+2] + 1.773 * (pData[j+1] - 128), 0, 255);*/
int R1 = clamp((298 * (pData[j] - 16) + 409 * (pData[j+3] - 128) + 128) >> 8, 0, 255), R2 = clamp((298 * (pData[j+2] - 16) + 409 * (pData[j+3] - 128) + 128) >> 8, 0, 255);
int G1 = clamp((298 * (pData[j] - 16) - 100 * (pData[j+1] - 128) - 208 * (pData[j+3] - 128) + 128) >> 8, 0, 255), G2 = clamp((298 * (pData[j+2] - 16) - 100 * (pData[j+1] - 128) - 208 * (pData[j+3] - 128) + 128) >> 8, 0, 255);
int B1 = clamp((298 * (pData[j] - 16) + 516 * (pData[j+1] - 128) + 128) >> 8, 0, 255), B2 = clamp((298 * (pData[j+2] - 16) + 516 * (pData[j+1] - 128) + 128) >> 8, 0, 255);
//printf("R: %d, G: %d, B: %d, R': %d, G': %d, B': %d \n", R1, G1, B1, R2, G2, B2);
m_RGB->imageData[i] = (char)R1;
m_RGB->imageData[i+1] = (char)G1;
m_RGB->imageData[i+2] = (char)B1;
m_RGB->imageData[i+3] = (char)R2;
m_RGB->imageData[i+4] = (char)G2;
m_RGB->imageData[i+5] = (char)B2;
/*m_RGB->imageData[i] = (char)(clamp(1.164 * (pData[j] - 16) + 1.793 * (Cr), 0, 255));
m_RGB->imageData[i+1] = (char)(clamp(1.164 * (pData[j] - 16) - 0.534 * (Cr) - 0.213 * (Cb), 0, 255));
m_RGB->imageData[i+2] = (char)(clamp(1.164 * (pData[j] - 16) + 2.115 * (Cb), 0, 255));
m_RGB->imageData[i+3] = (char)(clamp(1.164 * (pData[j+2] - 16) + 1.793 * (Cr), 0, 255));
m_RGB->imageData[i+4] = (char)(clamp(1.164 * (pData[j+2] - 16) - 0.534 * (Cr) - 0.213 * (Cb), 0, 255));
m_RGB->imageData[i+5] = (char)(clamp(1.164 * (pData[j+2] - 16) + 2.115 * (Cb), 0, 255));*/
}
Any help is greatly appreciated.
Some clues to help you along:
You are confusing Cr with Cb.
Assuming UYVY/422
Y1 = data[j+0];
Cr = data[j+1];
Y2 = data[j+2];
Cb = data[j+3];
Your conversion calculation are wierd, and incorrect for HD.
For SD
R = max(0, min(255, 1.164(Y - 16) + 1.596(Cr - 128)));
G = max(0, min(255, 1.164(Y - 16) - 0.813(Cr - 128) - 0.391(Cb - 128)));
B = max(0, min(255, 1.164(Y - 16) + 2.018(Cr - 128)));
For HD
R = max(0, min(255, 1.164(Y - 16) + 1.793(Cr - 128)));
G = max(0, min(255, 1.164(Y - 16) - 0.534(Cr - 128) - 0.213(Cb - 128)));
B = max(0, min(255, 1.164(Y - 16) + 2.115(Cr - 128)));
You could simply use ConvertFrame which is a part of the Decklink SDK.
Your problem is that there are lots of YUV422 formats out there. You must find the exact one (the FOURCC index for the specific video you're using), and then figure out the correct way to decode it.
What you can do is to save some video from your board, open it in VLC, and look at the Codec details to find the exact FOURCC used.
http://www.fourcc.org/yuv.php
Assuming packed 422 I don't see any of your blocks sampling the input data correctly. In packed 422 the input data will go Y1U1Y2V1 Y3U2Y4V2 where the overall image is a Y (luma) image at full resolution and one each of U and V each at half horizontal resolution.
Here's where I would start: Unpack alternating values of the input and extract a grayscale image:
for (uint i = 0, j = 0; i < 1280 * 720 * 3; i += 3, j += 2) {
m_RGB->imageData[i] = pData[j];
m_RGB->imageData[i+1] = pData[j];
m_RGB->imageData[i+2] = pData[j];
}
Once you have that tuned to produce a grayscale image then introduce U and V by looking at pData[j+1] and pData[j+3] (or, on even pixels, pData[j-1] and pData[j+1]). Simplifying that is why some algorithms do two YUV pixels at a time.
When that works consider extracting the U and V images and properly resampling them to full resolution to produce a 444 image. Simply duplicating U and V for adjacent pixels is like upscaling by duplicating pixels.
(Note that other arrangements like 420 have even more complicated co-siting)
I also struggled with the conversion
// Get the bytes
var u = bytes[0];
var y1 = bytes[1];
var v = bytes[2];
var y2 = bytes[3];
// Convert, cast to signed byte is important!
var r = y + (1.403 * (sbyte)v);
var g = y - (0.344 * (sbyte)u) - (0.714 * (sbyte)v);
var b = y + (1.770 * (sbyte)u);
if (r < 0)
r = 0;
else if (r > 255)
r = 255;
if (g < 0)
g = 0;
else if (g > 255)
g = 255;
if (b < 0)
b = 0;
else if (b > 255)
b = 255;
return Color.FromArgb((byte)r, (byte)g, (byte)b);
u and v are sbyte, and y is just a byte.