#include "ConvertResolutionYUV.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <Windows.h>
#define ABS(x) (x > 0 ? (x) : (-x))
#define clip(a, min, max) (a > max ? max : (a > min ? a : min))
#define INTEGER 1
int gcd(int a, int b)
{
if(b)
{
return gcd(b, a%b);
}
else
{
return a;
}
}
float S(float x)
{
if(ABS(x) < 1.0)
{
//1-2*Abs(x)^2+Abs(x)^3
return (1.0 - 2.0*x*x + ABS(x*x*x));
}
else if(ABS(x) >= 1.0 && ABS(x) < 2)
{
//4-8*Abs(x)+5*Abs(x)^2-Abs(x)^3
return (4.0 - 8.0*ABS(x) + 5.0*x*x - ABS(x*x*x));
}
else
{
return 0;
}
}
/**************************************************************
Matrix multiplication A x B = C
Input: A[m x p], B[p x n]
Output: C[m x n]
***************************************************************/
void MatrixMultiply(float *A, float *B, float *C, int m, int p, int n)
{
int i,j,k;
float sum;
for ( i = 0; i < m; i++)
{
for ( j = 0; j < n; j++)
{
sum = 0;
for ( k = 0; k < p; k++)
{
sum = sum + A[i * p + k] * B[k * n + j];
}
C[i*n +j] = sum;
}
}
}
/**************************************************************
Matrix multiplication A x B = C
Input: A[m x p], B[p x n]
Output: C[m x n]
***************************************************************/
void MatrixMultiply_Int(int *A, int *B, int *C, int m, int p, int n)
{
int i,j,k;
int sum;
for ( i = 0; i < m; i++)
{
for ( j = 0; j < n; j++)
{
sum = 0;
for ( k = 0; k < p; k++)
{
sum += A[i * p + k] * B[k * n + j];
}
C[i*n +j] = sum;
}
}
}
void Convolution1441(int *A, int *B, int *C, int *D)
{
int a, b, c, d;
a = A[0]*B[0] + A[1]*B[4] + A[2]*B[8] + A[3]*B[12];
b = A[0]*B[1] + A[1]*B[5] + A[2]*B[9] + A[3]*B[13];
c = A[0]*B[2] + A[1]*B[6] + A[2]*B[10] + A[3]*B[14];
d = A[0]*B[3] + A[1]*B[7] + A[2]*B[11] + A[3]*B[15];
*D = a*C[0] + b*C[1] + c*C[2] + d*C[3];
}
unsigned long long t_conv = 0;
CYUVResolution::CYUVResolution()
{
T1 = NULL;
T2 = NULL;
T3 = NULL;
T4 = NULL;
SSx1 = NULL;
SSy1 = NULL;
SSx2 = NULL;
SSy2 = NULL;
SSx3 = NULL;
SSy3 = NULL;
SSx4 = NULL;
SSy4 = NULL;
}
CYUVResolution::~CYUVResolution()
{
if (T1)
{
free(T1);
T1 = NULL;
}
if (T2)
{
free(T2);
T2 = NULL;
}
if (T3)
{
free(T3);
T3 = NULL;
}
if (T4)
{
free(T4);
T4 = NULL;
}
if (SSx1)
{
free(SSx1);
SSx1 = NULL;
}
if (SSx2)
{
free(SSx2);
SSx2 = NULL;
}
if (SSx3)
{
free(SSx3);
SSx3 = NULL;
}
if (SSx4)
{
free(SSx4);
SSx4 = NULL;
}
if (SSy1)
{
free(SSy1);
SSy1 = NULL;
}
if (SSy2)
{
free(SSy2);
SSy2 = NULL;
}
if (SSy3)
{
free(SSy3);
SSy3 = NULL;
}
if (SSy4)
{
free(SSy4);
SSy4 = NULL;
}
}
int CYUVResolution::Init(int iIntWidth, int iInHeight, int iOutWidth, int iOutHeight, int algorithm)
{
iAlgorithm = algorithm;
inWidth = iIntWidth;
inHeight = iInHeight;
outWidth = iOutWidth;
outHeight = iOutHeight;
int outWidth_cr = outWidth / 2;
int outHeight_cr = outHeight / 2;
T1 = (int*)malloc(outWidth_cr*sizeof(int));
T2 = (int*)malloc(outHeight_cr*sizeof(int));
T3 = (int*)malloc(outWidth*sizeof(int));
T4 = (int*)malloc(outHeight*sizeof(int));
SSx1 = (int*)malloc(outWidth*sizeof(int));
SSx2 = (int*)malloc(outWidth*sizeof(int));
SSx3 = (int*)malloc(outWidth*sizeof(int));
SSx4 = (int*)malloc(outWidth*sizeof(int));
SSy1 = (int*)malloc(outHeight*sizeof(int));
SSy2 = (int*)malloc(outHeight*sizeof(int));
SSy3 = (int*)malloc(outHeight*sizeof(int));
SSy4 = (int*)malloc(outHeight*sizeof(int));
return 0;
}
int CYUVResolution::ConvertYUV(unsigned char *src, unsigned char *dst)
{
return scale(iAlgorithm, src, inWidth, src + inWidth * inHeight, inWidth/2, src + inWidth * inHeight * 5 / 4,
inWidth/2, inWidth, inHeight, outWidth, outHeight, dst, dst+outWidth*outHeight, dst+outWidth*outHeight*5/4);
}
int CYUVResolution::scale(unsigned char algorithm,
unsigned char *pYIn, int lineY,
unsigned char *pCbIn, int lineCb,
unsigned char *pCrIn, int lineCr,
int srcWidth, int srcHeight,
int outWidth, int outHeight,
unsigned char *pYOut,
unsigned char *pCbOut,
unsigned char *pCrOut)
{
float rx = (float)outWidth/(float)srcWidth;
float ry = (float)outHeight/(float)srcHeight;
int x = 0, y = 0;
int xx = 0, yy = 0;
int outWidth_cr = outWidth / 2;
int outHeight_cr = outHeight / 2;
int srcWidth_cr = srcWidth / 2;
int srcHeight_cr = srcHeight / 2;
float c0, c1, c2, c3;
float u, v;
int uu, vv;
unsigned char *p = NULL, *p1 = NULL;
//unsigned long long t1, t2, t3, t4;
float A[4], B[16], C[4], tmp1[4], tmp2[1];
int AA[4], BB[16], CC[4], tt1[4], tt2;
int *C0=NULL, *C1=NULL, *C2=NULL, *C3=NULL;
unsigned char* pend = pYIn + lineY * srcHeight - 1;
int x_ratio = (int) (((srcWidth - 1) << 8) / outWidth);
int y_ratio = (int) (((srcHeight - 1) << 8) / outHeight);
int i, j;
int yr, y_dif, one_min_y_diff, y_diff;
int y_index, xr, x_diff, one_min_x_diff, index, Mult1, Mult2, Mult3, Mult4;
// Rational ratio
int gcdw = outWidth-srcWidth;//gcd(outWidth, srcWidth);
int gcdh = outHeight-srcHeight;//gcd(outHeight, srcHeight);
int rx_num = outWidth/gcdw;
int rx_den = srcWidth/gcdw;
int ry_num = outHeight/gcdh;
int ry_den = srcHeight/gcdh;
switch(algorithm)
{
case 0:
// cubic
for(y=0; y<outHeight; y++)
{
for(x=0; x<outWidth; x++)
{
//g(x, y) = f(x/r, y/r) = f(x*rx_den/rx_num, y*ry_den/ry_num)
xx = clip((int)((float)x / rx), 0, srcWidth-1);
yy = clip((int)((float)y / ry), 0, srcHeight-1);
pYOut[y*outWidth+x] = pYIn[yy*lineY + xx];
}
}
for(y=0; y<outHeight_cr; y++)
{
for(x=0; x<outWidth_cr; x++)
{
//g(x, y) = f(x/r, y/r) = f(x*rx_den/rx_num, y*ry_den/ry_num)
xx = clip((int)((float)x / rx), 0, srcWidth_cr-1);
yy = clip((int)((float)y / ry), 0, srcHeight_cr-1);
pCbOut[y*outWidth_cr+x] = pCbIn[yy*lineCb + xx];
}
}
for(y=0; y<outHeight_cr; y++)
{
for(x=0; x<outWidth_cr; x++)
{
//g(x, y) = f(x/r, y/r) = f(x*rx_den/rx_num, y*ry_den/ry_num)
xx = clip((int)((float)x / rx), 0, srcWidth_cr-1);
yy = clip((int)((float)y / ry), 0, srcHeight_cr-1);
pCrOut[y*outWidth_cr+x] = pCrIn[yy*lineCr + xx];
}
}
break;
case 1:
// bilinear
for(y=0; y<outHeight; y++)
{
for(x=0; x<outWidth; x++)
{
//g(x, y) = (1-c0)(1-c2)f(xx,yy) + (1-c2)(1-c1)f(xx,yy+1) + (1-c1)(1-c3)f(xx+1,yy) + (1-c0)(1-c3)f(xx+1,yy+1)
c0 = (((float)y / ry) - (int)((float)y / ry));
c1 = ((int)((float)y / ry) + 1 - ((float)y / ry));
c2 = (((float)x / rx) - (int)((float)x / rx));
c3 = ((int)((float)x / rx) + 1 - ((float)x / rx));
xx = clip((int)((float)x / rx), 0, srcWidth-1);
yy = clip((int)((float)y / ry), 0, srcHeight-1);
pYOut[y*outWidth+x] = (float)((1.0-c0)*(1.0-c2)*pYIn[yy*lin