summaryrefslogtreecommitdiffstats
path: root/postproc
diff options
context:
space:
mode:
authormichael <michael@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-07-04 13:08:37 +0000
committermichael <michael@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-07-04 13:08:37 +0000
commitde90a774d9e18f6241380d280e7ee8ddaca9e068 (patch)
treee91e08f25c0e720fe5cd8f305801c11f1e91d4d0 /postproc
parenteb7b9ab756a962e93394c978acacdd4530090895 (diff)
downloadmpv-de90a774d9e18f6241380d280e7ee8ddaca9e068.tar.bz2
mpv-de90a774d9e18f6241380d280e7ee8ddaca9e068.tar.xz
more scaling algos
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@6638 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'postproc')
-rw-r--r--postproc/swscale.c141
-rw-r--r--postproc/swscale.h16
2 files changed, 107 insertions, 50 deletions
diff --git a/postproc/swscale.c b/postproc/swscale.c
index bb27b4f167..12d5fbc10d 100644
--- a/postproc/swscale.c
+++ b/postproc/swscale.c
@@ -958,6 +958,10 @@ void swsGetFlagsAndFilterFromCmdLine(int *flags, SwsFilter **srcFilterParam, Sws
case 4: *flags|= SWS_POINT; break;
case 5: *flags|= SWS_AREA; break;
case 6: *flags|= SWS_BICUBLIN; break;
+ case 7: *flags|= SWS_GAUSS; break;
+ case 8: *flags|= SWS_SINC; break;
+ case 9: *flags|= SWS_LANCZOS; break;
+ case 10:*flags|= SWS_SPLINE; break;
default:*flags|= SWS_BILINEAR; break;
}
@@ -975,6 +979,16 @@ SwsContext *getSwsContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW
return getSwsContext(srcW, srcH, srcFormat, dstW, dstH, dstFormat, flags, srcFilterParam, dstFilterParam);
}
+static double getSplineCoeff(double a, double b, double c, double d, double dist)
+{
+// printf("%f %f %f %f %f\n", a,b,c,d,dist);
+ if(dist<=1.0) return ((d*dist + c)*dist + b)*dist +a;
+ else return getSplineCoeff( 0.0,
+ b+ 2.0*c + 3.0*d,
+ c + 3.0*d,
+ -b- 3.0*c - 6.0*d,
+ dist-1.0);
+}
static inline void initFilter(int16_t **outFilter, int16_t **filterPos, int *outFilterSize, int xInc,
int srcW, int dstW, int filterAlign, int one, int flags,
@@ -1025,7 +1039,7 @@ static inline void initFilter(int16_t **outFilter, int16_t **filterPos, int *out
xDstInSrc+= xInc;
}
}
- else if(xInc <= (1<<16) || (flags&SWS_FAST_BILINEAR)) // upscale
+ else if((xInc <= (1<<16) && (flags&SWS_AREA)) || (flags&SWS_FAST_BILINEAR)) // bilinear upscale
{
int i;
int xDstInSrc;
@@ -1041,32 +1055,6 @@ static inline void initFilter(int16_t **outFilter, int16_t **filterPos, int *out
int j;
(*filterPos)[i]= xx;
- if((flags & SWS_BICUBIC) || (flags & SWS_X))
- {
- double d= ABS(((xx+1)<<16) - xDstInSrc)/(double)(1<<16);
- double y1,y2,y3,y4;
- double A= -0.6;
- if(flags & SWS_BICUBIC){
- // Equation is from VirtualDub
- y1 = ( + A*d - 2.0*A*d*d + A*d*d*d);
- y2 = (+ 1.0 - (A+3.0)*d*d + (A+2.0)*d*d*d);
- y3 = ( - A*d + (2.0*A+3.0)*d*d - (A+2.0)*d*d*d);
- y4 = ( + A*d*d - A*d*d*d);
- }else{
- // cubic interpolation (derived it myself)
- y1 = ( -2.0*d + 3.0*d*d - 1.0*d*d*d)/6.0;
- y2 = (6.0 -3.0*d - 6.0*d*d + 3.0*d*d*d)/6.0;
- y3 = ( +6.0*d + 3.0*d*d - 3.0*d*d*d)/6.0;
- y4 = ( -1.0*d + 1.0*d*d*d)/6.0;
- }
-
- filter[i*filterSize + 0]= y1;
- filter[i*filterSize + 1]= y2;
- filter[i*filterSize + 2]= y3;
- filter[i*filterSize + 3]= y4;
- }
- else
- {
//Bilinear upscale / linear interpolate / Area averaging
for(j=0; j<filterSize; j++)
{
@@ -1076,35 +1064,48 @@ static inline void initFilter(int16_t **outFilter, int16_t **filterPos, int *out
filter[i*filterSize + j]= coeff;
xx++;
}
- }
xDstInSrc+= xInc;
}
}
- else // downscale
+ else
{
- int xDstInSrc;
- ASSERT(dstW <= srcW)
+ double xDstInSrc;
+ double sizeFactor, filterSizeInSrc;
+ const double xInc1= (double)xInc / (double)(1<<16);
+ int param= (flags&SWS_PARAM_MASK)>>SWS_PARAM_SHIFT;
+
+ if (flags&SWS_BICUBIC) sizeFactor= 4.0;
+ else if(flags&SWS_X) sizeFactor= 8.0;
+ else if(flags&SWS_AREA) sizeFactor= 1.0; //downscale only, for upscale it is bilinear
+ else if(flags&SWS_GAUSS) sizeFactor= 8.0; // infinite ;)
+ else if(flags&SWS_LANCZOS) sizeFactor= param ? 2.0*param : 6.0;
+ else if(flags&SWS_SINC) sizeFactor= 100.0; // infinite ;)
+ else if(flags&SWS_SPLINE) sizeFactor= 20.0; // infinite ;)
+ else if(flags&SWS_BILINEAR) sizeFactor= 2.0;
+ else ASSERT(0)
+
+ if(xInc1 <= 1.0) filterSizeInSrc= sizeFactor; // upscale
+ else filterSizeInSrc= sizeFactor*srcW / (double)dstW;
- if(flags&SWS_BICUBIC) filterSize= (int)ceil(1 + 4.0*srcW / (double)dstW);
- else if(flags&SWS_X) filterSize= (int)ceil(1 + 4.0*srcW / (double)dstW);
- else if(flags&SWS_AREA) filterSize= (int)ceil(1 + 1.0*srcW / (double)dstW);
- else /* BILINEAR */ filterSize= (int)ceil(1 + 2.0*srcW / (double)dstW);
- filter= (double*)memalign(8, dstW*sizeof(double)*filterSize);
+ filterSize= (int)ceil(1 + filterSizeInSrc); // will be reduced later if possible
+ if(filterSize > srcW-2) filterSize=srcW-2;
- xDstInSrc= xInc/2 - 0x8000;
+ filter= (double*)memalign(16, dstW*sizeof(double)*filterSize);
+
+ xDstInSrc= xInc1 / 2.0 - 0.5;
for(i=0; i<dstW; i++)
{
- int xx= (int)((double)xDstInSrc/(double)(1<<16) - (filterSize-1)*0.5 + 0.5);
+ int xx= (int)(xDstInSrc - (filterSize-1)*0.5 + 0.5);
int j;
(*filterPos)[i]= xx;
for(j=0; j<filterSize; j++)
{
- double d= ABS((xx<<16) - xDstInSrc)/(double)xInc;
+ double d= ABS(xx - xDstInSrc)/filterSizeInSrc*sizeFactor;
double coeff;
- if((flags & SWS_BICUBIC) || (flags & SWS_X))
+ if(flags & SWS_BICUBIC)
{
- double A= -0.75;
-// d*=2;
+ double A= param ? -param*0.01 : -0.60;
+
// Equation is from VirtualDub
if(d<1.0)
coeff = (1.0 - (A+3.0)*d*d + (A+2.0)*d*d*d);
@@ -1113,22 +1114,62 @@ static inline void initFilter(int16_t **outFilter, int16_t **filterPos, int *out
else
coeff=0.0;
}
+/* else if(flags & SWS_X)
+ {
+ double p= param ? param*0.01 : 0.3;
+ coeff = d ? sin(d*PI)/(d*PI) : 1.0;
+ coeff*= pow(2.0, - p*d*d);
+ }*/
+ else if(flags & SWS_X)
+ {
+ double A= param ? param*0.1 : 1.0;
+
+ if(d<1.0)
+ coeff = cos(d*PI);
+ else
+ coeff=-1.0;
+ if(coeff<0.0) coeff= -pow(-coeff, A);
+ else coeff= pow( coeff, A);
+ coeff= coeff*0.5 + 0.5;
+ }
else if(flags & SWS_AREA)
{
- double srcPixelSize= (1<<16)/(double)xInc;
+ double srcPixelSize= 1.0/xInc1;
if(d + srcPixelSize/2 < 0.5) coeff= 1.0;
else if(d - srcPixelSize/2 < 0.5) coeff= (0.5-d)/srcPixelSize + 0.5;
else coeff=0.0;
}
- else
+ else if(flags & SWS_GAUSS)
+ {
+ double p= param ? param*0.1 : 3.0;
+ coeff = pow(2.0, - p*d*d);
+ }
+ else if(flags & SWS_SINC)
+ {
+ coeff = d ? sin(d*PI)/(d*PI) : 1.0;
+ }
+ else if(flags & SWS_LANCZOS)
+ {
+ double p= param ? param : 3.0;
+ coeff = d ? sin(d*PI)*sin(d*PI/p)/(d*d*PI*PI/p) : 1.0;
+ if(d>p) coeff=0;
+ }
+ else if(flags & SWS_BILINEAR)
{
coeff= 1.0 - d;
if(coeff<0) coeff=0;
}
+ else if(flags & SWS_SPLINE)
+ {
+ double p=-2.196152422706632;
+ coeff = getSplineCoeff(1.0, 0.0, p, -p-1.0, d);
+ }
+ else ASSERT(0)
+
filter[i*filterSize + j]= coeff;
xx++;
}
- xDstInSrc+= xInc;
+ xDstInSrc+= xInc1;
}
}
@@ -2178,7 +2219,15 @@ SwsContext *getSwsContext(int srcW, int srcH, int srcFormat, int dstW, int dstH,
else if(flags&SWS_AREA)
MSG_INFO("\nSwScaler: Area Averageing scaler, ");
else if(flags&SWS_BICUBLIN)
- MSG_INFO("\nSwScaler: luma BICUBIC / chroma BILINEAR, ");
+ MSG_INFO("\nSwScaler: luma BICUBIC / chroma BILINEAR scaler, ");
+ else if(flags&SWS_GAUSS)
+ MSG_INFO("\nSwScaler: Gaussian scaler, ");
+ else if(flags&SWS_SINC)
+ MSG_INFO("\nSwScaler: Sinc scaler, ");
+ else if(flags&SWS_LANCZOS)
+ MSG_INFO("\nSwScaler: Lanczos scaler, ");
+ else if(flags&SWS_SPLINE)
+ MSG_INFO("\nSwScaler: Bicubic spline scaler, ");
else
MSG_INFO("\nSwScaler: ehh flags invalid?! ");
diff --git a/postproc/swscale.h b/postproc/swscale.h
index a3f5595aa4..54f8c71ba0 100644
--- a/postproc/swscale.h
+++ b/postproc/swscale.h
@@ -24,18 +24,26 @@
#define SWS_POINT 0x10
#define SWS_AREA 0x20
#define SWS_BICUBLIN 0x40
+#define SWS_GAUSS 0x80
+#define SWS_SINC 0x100
+#define SWS_LANCZOS 0x200
+#define SWS_SPLINE 0x400
-#define SWS_SRC_V_CHR_DROP_MASK 0x300
-#define SWS_SRC_V_CHR_DROP_SHIFT 8
+#define SWS_SRC_V_CHR_DROP_MASK 0x30000
+#define SWS_SRC_V_CHR_DROP_SHIFT 16
-//the following 4 flags are not completly implemented
+#define SWS_PARAM_MASK 0x3FC0000
+#define SWS_PARAM_SHIFT 18
+
+#define SWS_PRINT_INFO 0x1000
+
+//the following 3 flags are not completly implemented
//internal chrominace subsamling info
#define SWS_FULL_CHR_H_INT 0x2000
//input subsampling info
#define SWS_FULL_CHR_H_INP 0x4000
#define SWS_DIRECT_BGR 0x8000
-#define SWS_PRINT_INFO 0x1000
#define SWS_MAX_REDUCE_CUTOFF 0.002