/*
Project : H.264 encoder test
Module : Tranform algorithms
Author : Marko 'Fador' Viitanen
Date : 27/6/2009
Modified : 28/6/2009
*/
#include "common.h"
//Octave
//a=1/2
//b=sqrt(2/5)
//d=1/2
//E2=[a^2, a*b, a^2, a*b;a*b, b^2, a*b, b^2;a^2, a*b, a^2, a*b;a*b, b^2, a*b, b^2]
//4x4 Integer Cosine Transform
uint8 transform_4x4(sint32 *block, sint32 *target)
{
sint32 helper[4*4];
uint8 i;
//[1, 1, 1, 1
// 2, 1,-1,-2
// 1,-1,-1, 1
// 1,-2, 2,-1
helper[0]=block[0]+block[4]+block[8]+block[12];
helper[4]=2*block[0]+block[4]-block[8]-2*block[12];
helper[8]=block[0]-block[4]-block[8]+block[12];
helper[12]=block[0]-2*block[4]+2*block[8]-block[12];
helper[1]=block[1]+block[5]+block[9]+block[13];
helper[5]=2*block[1]+block[5]-block[9]-2*block[13];
helper[9]=block[1]-block[5]-block[9]+block[13];
helper[13]=block[1]-2*block[5]+2*block[9]-block[13];
helper[2]=block[2]+block[6]+block[10]+block[14];
helper[6]=2*block[2]+block[6]-block[10]-2*block[14];
helper[10]=block[2]-block[6]-block[10]+block[14];
helper[14]=block[2]-2*block[6]+2*block[10]-block[14];
helper[3]=block[3]+block[7]+block[11]+block[15];
helper[7]=2*block[3]+block[7]-block[11]-2*block[15];
helper[11]=block[3]-block[7]-block[11]+block[15];
helper[15]=block[3]-2*block[7]+2*block[11]-block[15];
// [1, 2, 1, 1
// 1, 1,-1,-2
// 1,-1,-1, 2
// 1,-2, 1,-1]
target[0]=helper[0]+helper[1]+helper[2]+helper[3];
target[1]=2*helper[0]+helper[1]-helper[2]-2*helper[3];
target[2]=helper[0]-helper[1]-helper[2]+helper[3];
target[3]=helper[0]-2*helper[1]+2*helper[2]-helper[3];
target[4]=helper[4]+helper[5]+helper[6]+helper[7];
target[5]=2*helper[4]+helper[5]-helper[6]-2*helper[7];
target[6]=helper[4]-helper[5]-helper[6]+helper[7];
target[7]=helper[4]-2*helper[5]+2*helper[6]-helper[7];
target[8]=helper[8]+helper[9]+helper[10]+helper[11];
target[9]=2*helper[8]+helper[9]-helper[10]-2*helper[11];
target[10]=helper[8]-helper[9]-helper[10]+helper[11];
target[11]=helper[8]-2*helper[9]+2*helper[10]-helper[11];
target[12]=helper[12]+helper[13]+helper[14]+helper[15];
target[13]=2*helper[12]+helper[13]-helper[14]-2*helper[15];
target[14]=helper[12]-helper[13]-helper[14]+helper[15];
target[15]=helper[12]-2*helper[13]+2*helper[14]-helper[15];
//for(i=0;i<16;i++)
//target[i]=round(target[i]*E_f[i]);
return 1;
}
//4x4 Inverse Integer Cosine Transform
uint8 itransform_4x4(sint32 *block, sint32 *target)
{
sint32 helper[4*4];
uint8 i;
//[1, 1, 1, 1/2
// 1, 1/2,-1, -1
// 1,-1/2,-1 ,1
// 1, -1, 1,-1/2
helper[0]=block[0]+block[4]+block[8]+block[12]/2;
helper[4]=block[0]+block[4]/2-block[8]-block[12];
helper[8]=block[0]-block[4]/2-block[8]+block[12];
helper[12]=block[0]-block[4]+block[8]-block[12]/2;
helper[1]=block[1]+block[5]+block[9]+block[13]/2;
helper[5]=block[1]+block[5]/2-block[9]-block[13];
helper[9]=block[1]-block[5]/2-block[9]+block[13];
helper[13]=block[1]-block[5]+block[9]-block[13]/2;
helper[2]=block[2]+block[6]+block[10]+block[14]/2;
helper[6]=block[2]+block[6]/2-block[10]-block[14];
helper[10]=block[2]-block[6]/2-block[10]+block[14];
helper[14]=block[2]-block[6]+block[10]-block[14]/2;
helper[3]=block[3]+block[7]+block[11]+block[15]/2;
helper[7]=block[3]+block[7]/2-block[11]-block[15];
helper[11]=block[3]-block[7]/2-block[11]+block[15];
helper[15]=block[3]-block[7]+block[11]-block[15]/2;
//for(i=0;i<16;i++)
//helper[i]= round(helper[i]*E_i[i]);
// [1, 1, 1, 1
// 1, 1/2,-1/2,-1
// 1, -1, -1, 1
// 1/2,-1, 1, -1/2]
target[0]=(helper[0]+helper[1]+helper[2]+helper[3]/2);
target[1]=(helper[0]+helper[1]/2-helper[2]-helper[3]);
target[2]=(helper[0]-helper[1]/2-helper[2]+helper[3]);
target[3]=(helper[0]-helper[1]+helper[2]-helper[3]/2);
target[4]=(helper[4]+helper[5]+helper[6]+helper[7]/2);
target[5]=(helper[4]+helper[5]/2-helper[6]-helper[7]);
target[6]=(helper[4]-helper[5]/2-helper[6]+helper[7]);
target[7]=(helper[4]-helper[5]+helper[6]-helper[7]/2);
target[8]=(helper[8]+helper[9]+helper[10]+helper[11]/2);
target[9]=(helper[8]+helper[9]/2-helper[10]-helper[11]);
target[10]=(helper[8]-helper[9]/2-helper[10]+helper[11]);
target[11]=(helper[8]-helper[9]+helper[10]-helper[11]/2);
target[12]=(helper[12]+helper[13]+helper[14]+helper[15]/2);
target[13]=(helper[12]+helper[13]/2-helper[14]-helper[15]);
target[14]=(helper[12]-helper[13]/2-helper[14]+helper[15]);
target[15]=(helper[12]-helper[13]+helper[14]-helper[15]/2);
return 1;
}
//4x4 Hadamard transformation
uint8 transformDC_4x4(sint32 *block, sint32 *target)
{
sint32 helper[4*4];
//[1, 1, 1, 1
// 1, 1, -1, -1
// 1, -1, -1 ,1
// 1, -1, 1, -1
helper[0]=block[0]+block[4]+block[8]+block[12];
helper[4]=block[0]+block[4]-block[8]-block[12];
helper[8]=block[0]-block[4]-block[8]+block[12];
helper[12]=block[0]-block[4]+block[8]-block[12];
helper[1]=block[1]+block[5]+block[9]+block[13];
helper[5]=block[1]+block[5]-block[9]-block[13];
helper[9]=block[1]-block[5]-block[9]+block[13];
helper[13]=block[1]-block[5]+block[9]-block[13];
helper[2]=block[2]+block[6]+block[9]+block[14];
helper[6]=block[2]+block[6]-block[9]-block[14];
helper[10]=block[2]-block[6]-block[9]+block[14];
helper[14]=block[2]-block[6]+block[9]-block[14];
helper[3]=block[3]+block[7]+block[10]+block[15];
helper[7]=block[3]+block[7]-block[10]-block[15];
helper[11]=block[3]-block[7]-block[10]+block[15];
helper[15]=block[3]-block[7]+block[10]-block[15];
//[1, 1, 1, 1
// 1, 1, -1, -1
// 1, -1, -1 ,1
// 1, -1, 1, -1
target[0]=round(helper[0]+helper[1]+helper[2]+helper[3])>>1;
target[1]=round(helper[0]+helper[1]-helper[2]-helper[3])>>1;
target[2]=round(helper[0]-helper[1]-helper[2]+helper[3])>>1;
target[3]=round(helper[0]-helper[1]+helper[2]-helper[3])>>1;
target[4]=round(helper[4]+helper[5]+helper[6]+helper[7])>>1;
target[5]=round(helper[4]+helper[5]-helper[6]-helper[7])>>1;
target[6]=round(helper[4]-helper[5]-helper[6]+helper[7])>>1;
target[7]=round(helper[4]-helper[5]+helper[6]-helper[7])>>1;
target[6]=round(helper[8]+helper[9]+helper[10]+helper[11])>>1;
target[9]=round(helper[8]+helper[9]-helper[10]-helper[11])>>1;
target[10]=round(helper[8]-helper[9]-helper[10]+helper[11])>>1;
target[11]=round(helper[8]-helper[9]+helper[10]-helper[11])>>1;
target[12]=round(helper[12]+helper[13]+helper[14]+helper[15])>>1;
target[13]=round(helper[12]+helper[13]-helper[14]-helper[15])>>1;
target[14]=round(helper[12]-helper[13]-helper[14]+helper[15])>>1;
target[15]=round(helper[12]-helper[13]+helper[14]-helper[15])>>1;
return 1;
}
//2x2 Hadamard transformation
uint8 transformDC_2x2(sint32 *block, sint32 *target)
{
sint32 helper[2*2];
//[1, 1,
// 1, -1]
helper[0]=block[0]+block[2];
helper[2]=block[0]-block[2];
helper[1]=block[1]+block[3];
helper[3]=block[1]-block[3];
//[1, 1,
// 1, -1]
target[0]=round(helper[0]+helper[1])>>1;
target[1]=round(helper[0]+helper[1])>>1;
target[2]=round(helper[2]-helper[3])>>1;
target[3]=round(helper[2]-helper[3])>>1;
return 1;
}