📄 sccoef.c
字号:
/*********************************************************************************
*********************************************************************************
**
** Name : sccoef.c
** Title : Video scaler coefficient generation module
** Author : P. Buxton
** Created : June 2001
**
** Copyright : 2001 by Imagination Technologies Limited. All rights reserved
** : No part of this software, either material or conceptual
** : may be copied or distributed, transmitted, transcribed,
** : stored in a retrieval system or translated into any
** : human or computer language in any form by any means,
** : electronic, mechanical, manual or other-wise, or
** : disclosed to third parties without the express written
** : permission of Imagination Technologies Limited, Unit 8,
** : HomePark Industrial Estate, King's Langley, Hertfordshire,
** : WD4 8LZ, U.K.
**
** Description : This module contains the algorithms necessary to generate
** the coefficients for a multitap video scaler.
**
** Platform : Platform independent (modify 'types.h' accordingly)
** $Log: sccoef.c $
**
** --- Revision Logs Removed ---
**
*********************************************************************************
*********************************************************************************/
#include "dp_types.h"
#include <math.h>
#include "sccoef.h"
/* This file abstracts the maths required to generate the coefficients
for scaling
The formula basically creates a discret weighted Sinc function.
table[t][i] = A - (1-A)*Cos(PI*Scale*(t+i/I))/(T/2))
x = PI*Scale*(T/2 -t -i/I + 0.000001)
sincfunc = sin(x)/x
table[t][i] *= sincfunc
where:
table[t][i] is the coeff for current tap and interpolation point. t is the current tap.
i is the current interpolation point.
I is the total interpolation points per tap. T is the total number of taps in the filter
Scale is the scaling factor clamped to [0.0, 1.0] A is a mystical number
Simulations show that the following setting are best:
A = 0.54
I = 8
T = 8 for horizontal scale, T = 4 for vertical scale
Note that the above function has reflective symmetry.
*/
#define Index(X,Y) ((X)+((Y)*T))
/***********************************************************************************************
*
* Function Name : DP_CalcCoefs
* Inputs : dwSrc - The length of the dimension which is being
* scaled FROM (i.e.: the source dimension),
* measured in pixels.
*
* dwDest - The length of the dimension which is being
* scaled TO (i.e.: the destination dimension),
* measured in pixels.
*
* Table - A pointer to an array of 'DP_UINT_8'
* variables, which the function will populate
* with the appropriate scaler tap
* co-efficients.
*
* I - The number of interpolation points to be
* calculated for each tap.
*
* T - The number of taps to be calculated.
*
* Outputs : Table - See above.
* Returns : Nothing.
* Globals Used : None.
*
* Description : This function calculates all filter taps for one dimensions (i.e.: height
* or width) of a video scaler.
*
***********************************************************************************************/
void DP_CalcCoefs ( DP_UINT_32 dwSrc,
DP_UINT_32 dwDest,
DP_UINT_8 Table [MAXTAP][MAXINTPT],
DP_UINT_32 I,
DP_UINT_32 T )
{
/* Due to the nature of the function we will only ever want to calculate the first half of the */
/* taps and the middle one (is this really a tap ?) as the seconda half are dervied from the */
/* first half as the function is symetrical. */
DP_FLOAT fScale;
DP_UINT_32 i,t;
DP_FLOAT flTable[MAXTAP][MAXINTPT]={0.0};
DP_INT_32 nTotal;
DP_FLOAT ftotal;
DP_INT_32 val;
DP_FLOAT fI, fT;
DP_INT_32 mT,mI; /* mirrored / middle Values for I and T */
DP_INT_32 startoffset=0;
fI = (DP_FLOAT) I;
fT = (DP_FLOAT) T;
fScale=((DP_FLOAT) dwDest/(DP_FLOAT) dwSrc);
if (fScale>1.0f)
{
fScale=1.0f;
}
for(i=0;i<I;i++)
{
for(t=0;t<T;t++)
{
flTable[t][i]=0.0;
}
}
for(i=0;i<I;i++)
{
for(t=0;t<T;t++)
{
flTable[t][i]= DP_SyncFunc((DP_FLOAT) i,(DP_FLOAT) t,fI,fT,fScale);
}
}
if(T>2)
{
for(t=0;t<((T/2)+(T%2));t++)
{
for(i=0;i<I;i++)
{
/* copy the table around the centrepoint */
mT=((T-1)-t)+(I-i)/I;
mI=(I-i)%I;
if(((DP_UINT_32)mI<I) && ((DP_UINT_32)mT<T) && ((t<((T/2)+(T%2)-1)) || ((I-i)>((T%2)*(I/2)))))
{
flTable[mT][mI]=flTable[t][i];
}
}
}
/* the middle value */
mT = T/2;
if ((T%2) != 0) {
mI = I/2;
} else {
mI = 0;
}
flTable[mT][mI]= DP_SyncFunc((DP_FLOAT) mI,(DP_FLOAT) mT,fI,fT,fScale);
}
/* normalize this interpolation point, and convert to 2.6 format trucating the result */
for(i=0;i<I;i++)
{
nTotal=0;
for(ftotal=0,t=0;t<T;t++)
{
ftotal+=flTable[t][i];
}
for(t=0;t<T;t++)
{
val=(DP_INT_32) ((flTable[t][i]*64.0f)/ftotal);
Table[t][i]=(DP_UINT_8) val;
nTotal+=val;
}
if((i<=(I/2)) || (T<=2)) /* normalize any floating point errors */
{
nTotal-=64;
if((i==(I/2)) && (T > 2))
{
nTotal/=2;
}
/* subtract the error from the I Point in the first tap ( this will not get */
/* mirrored, as it would go off the end). */
Table[0][i]=(DP_UINT_8) (Table[0][i]-(DP_UINT_8) nTotal);
}
}
/* copy the normalised table around the centrepoint */
if(T>2)
{
for(t=0;t<((T/2)+(T%2));t++)
{
for(i=0;i<I;i++)
{
mT=((T-1)-t)+(I-i)/I;
mI=(I-i)%I;
if(((DP_UINT_32)mI<I) && ((DP_UINT_32)mT<T) && ((t<((T/2)+(T%2)-1)) || ((I-i)>((T%2)*(I/2)))))
{
Table[mT][mI]=Table[t][i];
}
}
}
}
}
/***********************************************************************************************
*
* Function Name : DP_SyncFunc
* Inputs : fi - The number of interpolation points being
* used.
*
* ft - The number of taps being used.
*
* fI - The current interpolation point being
* considered.
*
* fT - The current tap being considered.
*
* fScale - The scaling factor being used.
*
* Outputs : None.
* Returns : The result of the sync. function for the current point.
* Globals Used : None.
*
* Description : Calculates a single point on a discrete weighted sync. function.
*
***********************************************************************************************/
__inline DP_FLOAT DP_SyncFunc ( DP_FLOAT fi,
DP_FLOAT ft,
DP_FLOAT fI,
DP_FLOAT fT,
DP_FLOAT fScale )
{
DP_FLOAT fSincfunc,fX;
DP_FLOAT fTempval;
DP_FLOAT fPI;
DP_FLOAT fA;
fPI=3.1415926535897f;
fA=0.54f;
fTempval= (DP_FLOAT) (fA - (1-fA)*DP_COS(2*fPI*fScale*(ft + fi/fI)/fT));
if ((fT/2 - ft - fi/fI) == 0) {
fSincfunc=1;
} else {
fX=fPI*fScale*(fT/2 - (ft + fi/fI));
fSincfunc = (DP_FLOAT) (DP_SIN(fX)/fX);
}
return ( fSincfunc * fTempval );
}
/*--------------------------- End of File --------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -