Mercurial > mplayer.hg
annotate libmpcodecs/vf_perspective.c @ 9593:e9a2af584986
Add the new -vf option wich is the same as vop in reverse order.
Syntax is we decided, so you can give the nomes or not with both
vop and vf. vf take precedence over vop.
author | albeu |
---|---|
date | Sat, 15 Mar 2003 18:01:02 +0000 |
parents | 6d97e935a071 |
children | 6ff3379a0862 |
rev | line source |
---|---|
8112 | 1 /* |
2 Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at> | |
3 | |
4 This program is free software; you can redistribute it and/or modify | |
5 it under the terms of the GNU General Public License as published by | |
6 the Free Software Foundation; either version 2 of the License, or | |
7 (at your option) any later version. | |
8 | |
9 This program is distributed in the hope that it will be useful, | |
10 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 GNU General Public License for more details. | |
13 | |
14 You should have received a copy of the GNU General Public License | |
15 along with this program; if not, write to the Free Software | |
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
17 */ | |
18 | |
19 #include <stdio.h> | |
20 #include <stdlib.h> | |
21 #include <string.h> | |
22 #include <inttypes.h> | |
23 #include <assert.h> | |
24 #include <math.h> | |
25 | |
26 #include "../config.h" | |
27 #include "../mp_msg.h" | |
28 | |
29 #ifdef HAVE_MALLOC_H | |
30 #include <malloc.h> | |
31 #endif | |
32 | |
33 #include "img_format.h" | |
34 #include "mp_image.h" | |
35 #include "vf.h" | |
36 #include "../libvo/fastmemcpy.h" | |
37 | |
38 #define SUB_PIXEL_BITS 8 | |
39 #define SUB_PIXELS (1<<SUB_PIXEL_BITS) | |
40 #define COEFF_BITS 11 | |
41 | |
42 //===========================================================================// | |
43 | |
44 struct vf_priv_s { | |
45 double ref[4][2]; | |
46 int32_t coeff[1<<SUB_PIXEL_BITS][4]; | |
47 int32_t (*pv)[2]; | |
48 int pvStride; | |
49 int cubic; | |
50 }; | |
51 | |
52 | |
53 /***************************************************************************/ | |
54 | |
55 static void initPv(struct vf_priv_s *priv, int W, int H){ | |
56 double a,b,c,d,e,f,g,h,D; | |
57 double (*ref)[2]= priv->ref; | |
58 int x,y; | |
59 | |
60 g= ( (ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0])*(ref[2][1] - ref[3][1]) | |
61 - (ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1])*(ref[2][0] - ref[3][0]))*H; | |
62 h= ( (ref[0][1] - ref[1][1] - ref[2][1] + ref[3][1])*(ref[1][0] - ref[3][0]) | |
63 - (ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0])*(ref[1][1] - ref[3][1]))*W; | |
64 D= (ref[1][0] - ref[3][0])*(ref[2][1] - ref[3][1]) | |
65 - (ref[2][0] - ref[3][0])*(ref[1][1] - ref[3][1]); | |
66 | |
67 a= D*(ref[1][0] - ref[0][0])*H + g*ref[1][0]; | |
68 b= D*(ref[2][0] - ref[0][0])*W + h*ref[2][0]; | |
69 c= D*ref[0][0]*W*H; | |
70 d= D*(ref[1][1] - ref[0][1])*H + g*ref[1][1]; | |
71 e= D*(ref[2][1] - ref[0][1])*W + h*ref[2][1]; | |
72 f= D*ref[0][1]*W*H; | |
73 | |
74 for(y=0; y<H; y++){ | |
75 for(x=0; x<W; x++){ | |
76 int u, v; | |
77 | |
78 u= (int)floor( SUB_PIXELS*(a*x + b*y + c)/(g*x + h*y + D*W*H) + 0.5); | |
79 v= (int)floor( SUB_PIXELS*(d*x + e*y + f)/(g*x + h*y + D*W*H) + 0.5); | |
80 | |
81 priv->pv[x + y*W][0]= u; | |
82 priv->pv[x + y*W][1]= v; | |
83 } | |
84 } | |
85 } | |
86 | |
87 static double getCoeff(double d){ | |
88 double A= -0.60; | |
89 double coeff; | |
90 | |
91 d= fabs(d); | |
92 | |
93 // Equation is from VirtualDub | |
94 if(d<1.0) | |
95 coeff = (1.0 - (A+3.0)*d*d + (A+2.0)*d*d*d); | |
96 else if(d<2.0) | |
97 coeff = (-4.0*A + 8.0*A*d - 5.0*A*d*d + A*d*d*d); | |
98 else | |
99 coeff=0.0; | |
100 | |
101 return coeff; | |
102 } | |
103 | |
104 static int config(struct vf_instance_s* vf, | |
105 int width, int height, int d_width, int d_height, | |
106 unsigned int flags, unsigned int outfmt){ | |
107 int i, j; | |
108 | |
109 vf->priv->pvStride= width; | |
110 vf->priv->pv= (void*)memalign(8, width*height*2*sizeof(int32_t)); | |
111 initPv(vf->priv, width, height); | |
112 | |
113 for(i=0; i<SUB_PIXELS; i++){ | |
114 double d= i/(double)SUB_PIXELS; | |
115 double temp[4]; | |
116 double sum=0; | |
117 | |
118 for(j=0; j<4; j++) | |
119 temp[j]= getCoeff(j - d - 1); | |
120 | |
121 for(j=0; j<4; j++) | |
122 sum+= temp[j]; | |
123 | |
124 for(j=0; j<4; j++) | |
125 vf->priv->coeff[i][j]= (int)floor((1<<COEFF_BITS)*temp[j]/sum + 0.5); | |
126 } | |
127 | |
128 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); | |
129 } | |
130 | |
131 static void uninit(struct vf_instance_s* vf){ | |
132 if(!vf->priv) return; | |
133 | |
134 if(vf->priv->pv) free(vf->priv->pv); | |
135 vf->priv->pv= NULL; | |
136 | |
137 free(vf->priv); | |
138 vf->priv=NULL; | |
139 } | |
140 | |
141 static inline void resampleCubic(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, struct vf_priv_s *privParam, int xShift, int yShift){ | |
142 int x, y; | |
143 struct vf_priv_s priv= *privParam; | |
144 | |
145 for(y=0; y<h; y++){ | |
146 for(x=0; x<w; x++){ | |
147 int u, v, subU, subV, sum, sx, sy; | |
148 | |
149 sx= x << xShift; | |
150 sy= y << yShift; | |
151 u= priv.pv[sx + sy*priv.pvStride][0]>>xShift; | |
152 v= priv.pv[sx + sy*priv.pvStride][1]>>yShift; | |
153 subU= u & (SUB_PIXELS-1); | |
154 subV= v & (SUB_PIXELS-1); | |
155 u >>= SUB_PIXEL_BITS; | |
156 v >>= SUB_PIXEL_BITS; | |
157 | |
158 if(u>0 && v>0 && u<w-2 && v<h-2){ | |
159 const int index= u + v*srcStride; | |
160 const int a= priv.coeff[subU][0]; | |
161 const int b= priv.coeff[subU][1]; | |
162 const int c= priv.coeff[subU][2]; | |
163 const int d= priv.coeff[subU][3]; | |
164 | |
165 sum= | |
166 priv.coeff[subV][0]*( a*src[index - 1 - srcStride] + b*src[index - 0 - srcStride] | |
167 + c*src[index + 1 - srcStride] + d*src[index + 2 - srcStride]) | |
168 +priv.coeff[subV][1]*( a*src[index - 1 ] + b*src[index - 0 ] | |
169 + c*src[index + 1 ] + d*src[index + 2 ]) | |
170 +priv.coeff[subV][2]*( a*src[index - 1 + srcStride] + b*src[index - 0 + srcStride] | |
171 + c*src[index + 1 + srcStride] + d*src[index + 2 + srcStride]) | |
172 +priv.coeff[subV][3]*( a*src[index - 1+2*srcStride] + b*src[index - 0+2*srcStride] | |
173 + c*src[index + 1+2*srcStride] + d*src[index + 2+2*srcStride]); | |
174 }else{ | |
175 int dx, dy; | |
176 sum=0; | |
177 | |
178 for(dy=0; dy<4; dy++){ | |
179 int iy= v + dy - 1; | |
180 if (iy< 0) iy=0; | |
181 else if(iy>=h) iy=h-1; | |
182 for(dx=0; dx<4; dx++){ | |
183 int ix= u + dx - 1; | |
184 if (ix< 0) ix=0; | |
185 else if(ix>=w) ix=w-1; | |
186 | |
187 sum+= priv.coeff[subU][dx]*priv.coeff[subV][dy] | |
188 *src[ ix + iy*srcStride]; | |
189 } | |
190 } | |
191 } | |
192 sum= (sum + (1<<(COEFF_BITS*2-1)) ) >> (COEFF_BITS*2); | |
193 if(sum&~255){ | |
194 if(sum<0) sum=0; | |
195 else sum=255; | |
196 } | |
197 dst[ x + y*dstStride]= sum; | |
198 } | |
199 } | |
200 } | |
201 | |
202 static inline void resampleLinear(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, | |
203 struct vf_priv_s *privParam, int xShift, int yShift){ | |
204 int x, y; | |
205 struct vf_priv_s priv= *privParam; | |
206 | |
207 for(y=0; y<h; y++){ | |
208 for(x=0; x<w; x++){ | |
209 int u, v, subU, subV, sum, sx, sy, index, subUI, subVI; | |
210 | |
211 sx= x << xShift; | |
212 sy= y << yShift; | |
213 u= priv.pv[sx + sy*priv.pvStride][0]>>xShift; | |
214 v= priv.pv[sx + sy*priv.pvStride][1]>>yShift; | |
215 subU= u & (SUB_PIXELS-1); | |
216 subV= v & (SUB_PIXELS-1); | |
217 u >>= SUB_PIXEL_BITS; | |
218 v >>= SUB_PIXEL_BITS; | |
219 index= u + v*srcStride; | |
220 subUI= SUB_PIXELS - subU; | |
221 subVI= SUB_PIXELS - subV; | |
222 | |
223 if((unsigned)u < (unsigned)(w - 1)){ | |
224 if((unsigned)v < (unsigned)(h - 1)){ | |
225 sum= subVI*(subUI*src[index ] + subU*src[index +1]) | |
226 +subV *(subUI*src[index+srcStride] + subU*src[index+srcStride+1]); | |
227 sum= (sum + (1<<(SUB_PIXEL_BITS*2-1)) ) >> (SUB_PIXEL_BITS*2); | |
228 }else{ | |
229 if(v<0) v= 0; | |
230 else v= h-1; | |
231 index= u + v*srcStride; | |
232 sum= subUI*src[index] + subU*src[index+1]; | |
233 sum= (sum + (1<<(SUB_PIXEL_BITS-1)) ) >> SUB_PIXEL_BITS; | |
234 } | |
235 }else{ | |
236 if((unsigned)v < (unsigned)(h - 1)){ | |
237 if(u<0) u= 0; | |
238 else u= w-1; | |
239 index= u + v*srcStride; | |
240 sum= subVI*src[index] + subV*src[index+srcStride]; | |
241 sum= (sum + (1<<(SUB_PIXEL_BITS-1)) ) >> SUB_PIXEL_BITS; | |
242 }else{ | |
243 if(u<0) u= 0; | |
244 else u= w-1; | |
245 if(v<0) v= 0; | |
246 else v= h-1; | |
247 index= u + v*srcStride; | |
248 sum= src[index]; | |
249 } | |
250 } | |
251 if(sum&~255){ | |
252 if(sum<0) sum=0; | |
253 else sum=255; | |
254 } | |
255 dst[ x + y*dstStride]= sum; | |
256 } | |
257 } | |
258 } | |
259 | |
260 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi){ | |
261 int cw= mpi->w >> mpi->chroma_x_shift; | |
262 int ch= mpi->h >> mpi->chroma_y_shift; | |
263 | |
264 mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt, | |
265 MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, | |
266 mpi->w,mpi->h); | |
267 | |
268 assert(mpi->flags&MP_IMGFLAG_PLANAR); | |
269 | |
270 if(vf->priv->cubic){ | |
271 resampleCubic(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0], | |
272 vf->priv, 0, 0); | |
273 resampleCubic(dmpi->planes[1], mpi->planes[1], cw , ch , dmpi->stride[1], mpi->stride[1], | |
274 vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift); | |
275 resampleCubic(dmpi->planes[2], mpi->planes[2], cw , ch , dmpi->stride[2], mpi->stride[2], | |
276 vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift); | |
277 }else{ | |
278 resampleLinear(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0], | |
279 vf->priv, 0, 0); | |
280 resampleLinear(dmpi->planes[1], mpi->planes[1], cw , ch , dmpi->stride[1], mpi->stride[1], | |
281 vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift); | |
282 resampleLinear(dmpi->planes[2], mpi->planes[2], cw , ch , dmpi->stride[2], mpi->stride[2], | |
283 vf->priv, mpi->chroma_x_shift, mpi->chroma_y_shift); | |
284 } | |
285 | |
286 return vf_next_put_image(vf,dmpi); | |
287 } | |
288 | |
289 //===========================================================================// | |
290 | |
291 static int query_format(struct vf_instance_s* vf, unsigned int fmt){ | |
292 switch(fmt) | |
293 { | |
294 case IMGFMT_YV12: | |
295 case IMGFMT_I420: | |
296 case IMGFMT_IYUV: | |
297 case IMGFMT_YVU9: | |
298 case IMGFMT_444P: | |
299 case IMGFMT_422P: | |
300 case IMGFMT_411P: | |
301 return vf_next_query_format(vf, fmt); | |
302 } | |
303 return 0; | |
304 } | |
305 | |
306 static int open(vf_instance_t *vf, char* args){ | |
307 int e; | |
308 | |
309 vf->config=config; | |
310 vf->put_image=put_image; | |
311 // vf->get_image=get_image; | |
312 vf->query_format=query_format; | |
313 vf->uninit=uninit; | |
314 vf->priv=malloc(sizeof(struct vf_priv_s)); | |
315 memset(vf->priv, 0, sizeof(struct vf_priv_s)); | |
316 | |
317 if(args==NULL) return 0; | |
318 | |
319 e=sscanf(args, "%lf:%lf:%lf:%lf:%lf:%lf:%lf:%lf:%d", | |
320 &vf->priv->ref[0][0], &vf->priv->ref[0][1], | |
321 &vf->priv->ref[1][0], &vf->priv->ref[1][1], | |
322 &vf->priv->ref[2][0], &vf->priv->ref[2][1], | |
323 &vf->priv->ref[3][0], &vf->priv->ref[3][1], | |
324 &vf->priv->cubic | |
325 ); | |
326 | |
327 if(e!=9) | |
328 return 0; | |
329 | |
330 return 1; | |
331 } | |
332 | |
333 vf_info_t vf_info_perspective = { | |
334 "perspective correcture", | |
335 "perspective", | |
336 "Michael Niedermayer", | |
337 "", | |
9593
e9a2af584986
Add the new -vf option wich is the same as vop in reverse order.
albeu
parents:
8112
diff
changeset
|
338 open, |
e9a2af584986
Add the new -vf option wich is the same as vop in reverse order.
albeu
parents:
8112
diff
changeset
|
339 NULL |
8112 | 340 }; |
341 | |
342 //===========================================================================// |