Browse code

more scaling algos

Originally committed as revision 6638 to svn://svn.mplayerhq.hu/mplayer/trunk/postproc

Michael Niedermayer authored on 2002/07/04 22:08:37
Showing 2 changed files
... ...
@@ -958,6 +958,10 @@ void swsGetFlagsAndFilterFromCmdLine(int *flags, SwsFilter **srcFilterParam, Sws
958 958
 		case 4: *flags|= SWS_POINT; break;
959 959
 		case 5: *flags|= SWS_AREA; break;
960 960
 		case 6: *flags|= SWS_BICUBLIN; break;
961
+		case 7: *flags|= SWS_GAUSS; break;
962
+		case 8: *flags|= SWS_SINC; break;
963
+		case 9: *flags|= SWS_LANCZOS; break;
964
+		case 10:*flags|= SWS_SPLINE; break;
961 965
 		default:*flags|= SWS_BILINEAR; break;
962 966
 	}
963 967
 	
... ...
@@ -975,6 +979,16 @@ SwsContext *getSwsContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW
975 975
 	return getSwsContext(srcW, srcH, srcFormat, dstW, dstH, dstFormat, flags, srcFilterParam, dstFilterParam);
976 976
 }
977 977
 
978
+static double getSplineCoeff(double a, double b, double c, double d, double dist)
979
+{
980
+//	printf("%f %f %f %f %f\n", a,b,c,d,dist);
981
+	if(dist<=1.0) 	return ((d*dist + c)*dist + b)*dist +a;
982
+	else		return getSplineCoeff(	0.0, 
983
+						 b+ 2.0*c + 3.0*d,
984
+						        c + 3.0*d,
985
+						-b- 3.0*c - 6.0*d,
986
+						dist-1.0);
987
+}
978 988
 
979 989
 static inline void initFilter(int16_t **outFilter, int16_t **filterPos, int *outFilterSize, int xInc,
980 990
 			      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
1025 1025
 			xDstInSrc+= xInc;
1026 1026
 		}
1027 1027
 	}
1028
-	else if(xInc <= (1<<16) || (flags&SWS_FAST_BILINEAR)) // upscale
1028
+	else if((xInc <= (1<<16) && (flags&SWS_AREA)) || (flags&SWS_FAST_BILINEAR)) // bilinear upscale
1029 1029
 	{
1030 1030
 		int i;
1031 1031
 		int xDstInSrc;
... ...
@@ -1041,32 +1055,6 @@ static inline void initFilter(int16_t **outFilter, int16_t **filterPos, int *out
1041 1041
 			int j;
1042 1042
 
1043 1043
 			(*filterPos)[i]= xx;
1044
-			if((flags & SWS_BICUBIC) || (flags & SWS_X))
1045
-			{
1046
-				double d= ABS(((xx+1)<<16) - xDstInSrc)/(double)(1<<16);
1047
-				double y1,y2,y3,y4;
1048
-				double A= -0.6;
1049
-				if(flags & SWS_BICUBIC){
1050
-						// Equation is from VirtualDub
1051
-					y1 = (        +     A*d -       2.0*A*d*d +       A*d*d*d);
1052
-					y2 = (+ 1.0             -     (A+3.0)*d*d + (A+2.0)*d*d*d);
1053
-					y3 = (        -     A*d + (2.0*A+3.0)*d*d - (A+2.0)*d*d*d);
1054
-					y4 = (                  +           A*d*d -       A*d*d*d);
1055
-				}else{
1056
-						// cubic interpolation (derived it myself)
1057
-					y1 = (    -2.0*d + 3.0*d*d - 1.0*d*d*d)/6.0;
1058
-					y2 = (6.0 -3.0*d - 6.0*d*d + 3.0*d*d*d)/6.0;
1059
-					y3 = (    +6.0*d + 3.0*d*d - 3.0*d*d*d)/6.0;
1060
-					y4 = (    -1.0*d           + 1.0*d*d*d)/6.0;
1061
-				}
1062
-
1063
-				filter[i*filterSize + 0]= y1;
1064
-				filter[i*filterSize + 1]= y2;
1065
-				filter[i*filterSize + 2]= y3;
1066
-				filter[i*filterSize + 3]= y4;
1067
-			}
1068
-			else
1069
-			{
1070 1044
 				//Bilinear upscale / linear interpolate / Area averaging
1071 1045
 				for(j=0; j<filterSize; j++)
1072 1046
 				{
... ...
@@ -1076,35 +1064,48 @@ static inline void initFilter(int16_t **outFilter, int16_t **filterPos, int *out
1076 1076
 					filter[i*filterSize + j]= coeff;
1077 1077
 					xx++;
1078 1078
 				}
1079
-			}
1080 1079
 			xDstInSrc+= xInc;
1081 1080
 		}
1082 1081
 	}
1083
-	else // downscale
1082
+	else
1084 1083
 	{
1085
-		int xDstInSrc;
1086
-		ASSERT(dstW <= srcW)
1084
+		double xDstInSrc;
1085
+		double sizeFactor, filterSizeInSrc;
1086
+		const double xInc1= (double)xInc / (double)(1<<16);
1087
+		int param= (flags&SWS_PARAM_MASK)>>SWS_PARAM_SHIFT;
1088
+
1089
+		if     (flags&SWS_BICUBIC)	sizeFactor= 4.0;
1090
+		else if(flags&SWS_X)		sizeFactor= 8.0;
1091
+		else if(flags&SWS_AREA)		sizeFactor= 1.0; //downscale only, for upscale it is bilinear
1092
+		else if(flags&SWS_GAUSS)	sizeFactor= 8.0;   // infinite ;)
1093
+		else if(flags&SWS_LANCZOS)	sizeFactor= param ? 2.0*param : 6.0;
1094
+		else if(flags&SWS_SINC)		sizeFactor= 100.0; // infinite ;)
1095
+		else if(flags&SWS_SPLINE)	sizeFactor= 20.0;  // infinite ;)
1096
+		else if(flags&SWS_BILINEAR)	sizeFactor= 2.0;
1097
+		else ASSERT(0)
1098
+		
1099
+		if(xInc1 <= 1.0)	filterSizeInSrc= sizeFactor; // upscale
1100
+		else			filterSizeInSrc= sizeFactor*srcW / (double)dstW;
1087 1101
 
1088
-		if(flags&SWS_BICUBIC)	filterSize= (int)ceil(1 + 4.0*srcW / (double)dstW);
1089
-		else if(flags&SWS_X)	filterSize= (int)ceil(1 + 4.0*srcW / (double)dstW);
1090
-		else if(flags&SWS_AREA)	filterSize= (int)ceil(1 + 1.0*srcW / (double)dstW);
1091
-		else /* BILINEAR */	filterSize= (int)ceil(1 + 2.0*srcW / (double)dstW);
1092
-		filter= (double*)memalign(8, dstW*sizeof(double)*filterSize);
1102
+		filterSize= (int)ceil(1 + filterSizeInSrc); // will be reduced later if possible
1103
+		if(filterSize > srcW-2) filterSize=srcW-2;
1093 1104
 
1094
-		xDstInSrc= xInc/2 - 0x8000;
1105
+		filter= (double*)memalign(16, dstW*sizeof(double)*filterSize);
1106
+
1107
+		xDstInSrc= xInc1 / 2.0 - 0.5;
1095 1108
 		for(i=0; i<dstW; i++)
1096 1109
 		{
1097
-			int xx= (int)((double)xDstInSrc/(double)(1<<16) - (filterSize-1)*0.5 + 0.5);
1110
+			int xx= (int)(xDstInSrc - (filterSize-1)*0.5 + 0.5);
1098 1111
 			int j;
1099 1112
 			(*filterPos)[i]= xx;
1100 1113
 			for(j=0; j<filterSize; j++)
1101 1114
 			{
1102
-				double d= ABS((xx<<16) - xDstInSrc)/(double)xInc;
1115
+				double d= ABS(xx - xDstInSrc)/filterSizeInSrc*sizeFactor;
1103 1116
 				double coeff;
1104
-				if((flags & SWS_BICUBIC) || (flags & SWS_X))
1117
+				if(flags & SWS_BICUBIC)
1105 1118
 				{
1106
-					double A= -0.75;
1107
-//					d*=2;
1119
+					double A= param ? -param*0.01 : -0.60;
1120
+					
1108 1121
 					// Equation is from VirtualDub
1109 1122
 					if(d<1.0)
1110 1123
 						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
1113 1113
 					else
1114 1114
 						coeff=0.0;
1115 1115
 				}
1116
+/*				else if(flags & SWS_X)
1117
+				{
1118
+					double p= param ? param*0.01 : 0.3;
1119
+					coeff = d ? sin(d*PI)/(d*PI) : 1.0;
1120
+					coeff*= pow(2.0, - p*d*d);
1121
+				}*/
1122
+				else if(flags & SWS_X)
1123
+				{
1124
+					double A= param ? param*0.1 : 1.0;
1125
+					
1126
+					if(d<1.0)
1127
+						coeff = cos(d*PI);
1128
+					else
1129
+						coeff=-1.0;
1130
+					if(coeff<0.0) 	coeff= -pow(-coeff, A);
1131
+					else		coeff=  pow( coeff, A);
1132
+					coeff= coeff*0.5 + 0.5;
1133
+				}
1116 1134
 				else if(flags & SWS_AREA)
1117 1135
 				{
1118
-					double srcPixelSize= (1<<16)/(double)xInc;
1136
+					double srcPixelSize= 1.0/xInc1;
1119 1137
 					if(d + srcPixelSize/2 < 0.5) coeff= 1.0;
1120 1138
 					else if(d - srcPixelSize/2 < 0.5) coeff= (0.5-d)/srcPixelSize + 0.5;
1121 1139
 					else coeff=0.0;
1122 1140
 				}
1123
-				else
1141
+				else if(flags & SWS_GAUSS)
1142
+				{
1143
+					double p= param ? param*0.1 : 3.0;
1144
+					coeff = pow(2.0, - p*d*d);
1145
+				}
1146
+				else if(flags & SWS_SINC)
1147
+				{
1148
+					coeff = d ? sin(d*PI)/(d*PI) : 1.0;
1149
+				}
1150
+				else if(flags & SWS_LANCZOS)
1151
+				{
1152
+					double p= param ? param : 3.0; 
1153
+					coeff = d ? sin(d*PI)*sin(d*PI/p)/(d*d*PI*PI/p) : 1.0;
1154
+					if(d>p) coeff=0;
1155
+				}
1156
+				else if(flags & SWS_BILINEAR)
1124 1157
 				{
1125 1158
 					coeff= 1.0 - d;
1126 1159
 					if(coeff<0) coeff=0;
1127 1160
 				}
1161
+				else if(flags & SWS_SPLINE)
1162
+				{
1163
+					double p=-2.196152422706632;
1164
+					coeff = getSplineCoeff(1.0, 0.0, p, -p-1.0, d);
1165
+				}
1166
+				else ASSERT(0)
1167
+
1128 1168
 				filter[i*filterSize + j]= coeff;
1129 1169
 				xx++;
1130 1170
 			}
1131
-			xDstInSrc+= xInc;
1171
+			xDstInSrc+= xInc1;
1132 1172
 		}
1133 1173
 	}
1134 1174
 
... ...
@@ -2178,7 +2219,15 @@ SwsContext *getSwsContext(int srcW, int srcH, int srcFormat, int dstW, int dstH,
2178 2178
 		else if(flags&SWS_AREA)
2179 2179
 			MSG_INFO("\nSwScaler: Area Averageing scaler, ");
2180 2180
 		else if(flags&SWS_BICUBLIN)
2181
-			MSG_INFO("\nSwScaler: luma BICUBIC / chroma BILINEAR, ");
2181
+			MSG_INFO("\nSwScaler: luma BICUBIC / chroma BILINEAR scaler, ");
2182
+		else if(flags&SWS_GAUSS)
2183
+			MSG_INFO("\nSwScaler: Gaussian scaler, ");
2184
+		else if(flags&SWS_SINC)
2185
+			MSG_INFO("\nSwScaler: Sinc scaler, ");
2186
+		else if(flags&SWS_LANCZOS)
2187
+			MSG_INFO("\nSwScaler: Lanczos scaler, ");
2188
+		else if(flags&SWS_SPLINE)
2189
+			MSG_INFO("\nSwScaler: Bicubic spline scaler, ");
2182 2190
 		else
2183 2191
 			MSG_INFO("\nSwScaler: ehh flags invalid?! ");
2184 2192
 
... ...
@@ -24,18 +24,26 @@
24 24
 #define SWS_POINT    0x10
25 25
 #define SWS_AREA     0x20
26 26
 #define SWS_BICUBLIN 0x40
27
+#define SWS_GAUSS    0x80
28
+#define SWS_SINC     0x100
29
+#define SWS_LANCZOS  0x200
30
+#define SWS_SPLINE   0x400
27 31
 
28
-#define SWS_SRC_V_CHR_DROP_MASK		0x300
29
-#define SWS_SRC_V_CHR_DROP_SHIFT	8
32
+#define SWS_SRC_V_CHR_DROP_MASK		0x30000
33
+#define SWS_SRC_V_CHR_DROP_SHIFT	16
30 34
 
31
-//the following 4 flags are not completly implemented
35
+#define SWS_PARAM_MASK			0x3FC0000
36
+#define SWS_PARAM_SHIFT			18
37
+
38
+#define SWS_PRINT_INFO		0x1000
39
+
40
+//the following 3 flags are not completly implemented
32 41
 //internal chrominace subsamling info
33 42
 #define SWS_FULL_CHR_H_INT	0x2000
34 43
 //input subsampling info
35 44
 #define SWS_FULL_CHR_H_INP	0x4000
36 45
 #define SWS_DIRECT_BGR		0x8000
37 46
 
38
-#define SWS_PRINT_INFO 0x1000
39 47
 
40 48
 #define SWS_MAX_REDUCE_CUTOFF 0.002
41 49