2 * Copyright (C) 2003 Daniel Moreno <comac@comac.darktech.org>
4 * This file is part of MPlayer.
6 * MPlayer is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * MPlayer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34 #include "img_format.h"
38 #define PARAM1_DEFAULT 4.0
39 #define PARAM2_DEFAULT 3.0
40 #define PARAM3_DEFAULT 6.0
42 //===========================================================================//
51 /***************************************************************************/
54 static int config(struct vf_instance_s
* vf
,
55 int width
, int height
, int d_width
, int d_height
,
56 unsigned int flags
, unsigned int outfmt
){
58 if(vf
->priv
->Line
) free(vf
->priv
->Line
);
59 vf
->priv
->Line
= malloc(width
);
61 // vf->default_caps &= !VFCAP_ACCEPT_STRIDE;
63 return vf_next_config(vf
,width
,height
,d_width
,d_height
,flags
,outfmt
);
67 static void uninit(struct vf_instance_s
* vf
)
72 #define LowPass(Prev, Curr, Coef) (Curr + Coef[Prev - Curr])
74 static void deNoise(unsigned char *Frame
, // mpi->planes[x]
75 unsigned char *FramePrev
, // pmpi->planes[x]
76 unsigned char *FrameDest
, // dmpi->planes[x]
77 unsigned char *LineAnt
, // vf->priv->Line (width bytes)
78 int W
, int H
, int sStride
, int pStride
, int dStride
,
79 int *Horizontal
, int *Vertical
, int *Temporal
)
82 int sLineOffs
= 0, pLineOffs
= 0, dLineOffs
= 0;
83 unsigned char PixelAnt
;
85 /* First pixel has no left nor top neighbor. Only previous frame */
86 LineAnt
[0] = PixelAnt
= Frame
[0];
87 FrameDest
[0] = LowPass(FramePrev
[0], LineAnt
[0], Temporal
);
89 /* Fist line has no top neighbor. Only left one for each pixel and
91 for (X
= 1; X
< W
; X
++)
93 PixelAnt
= LowPass(PixelAnt
, Frame
[X
], Horizontal
);
94 LineAnt
[X
] = PixelAnt
;
95 FrameDest
[X
] = LowPass(FramePrev
[X
], LineAnt
[X
], Temporal
);
98 for (Y
= 1; Y
< H
; Y
++)
100 sLineOffs
+= sStride
, pLineOffs
+= pStride
, dLineOffs
+= dStride
;
101 /* First pixel on each line doesn't have previous pixel */
102 PixelAnt
= Frame
[sLineOffs
];
103 LineAnt
[0] = LowPass(LineAnt
[0], PixelAnt
, Vertical
);
104 FrameDest
[dLineOffs
] = LowPass(FramePrev
[pLineOffs
], LineAnt
[0], Temporal
);
106 for (X
= 1; X
< W
; X
++)
108 /* The rest are normal */
109 PixelAnt
= LowPass(PixelAnt
, Frame
[sLineOffs
+X
], Horizontal
);
110 LineAnt
[X
] = LowPass(LineAnt
[X
], PixelAnt
, Vertical
);
111 FrameDest
[dLineOffs
+X
] = LowPass(FramePrev
[pLineOffs
+X
], LineAnt
[X
], Temporal
);
118 static int put_image(struct vf_instance_s
* vf
, mp_image_t
*mpi
, double pts
){
119 int cw
= mpi
->w
>> mpi
->chroma_x_shift
;
120 int ch
= mpi
->h
>> mpi
->chroma_y_shift
;
121 int W
= mpi
->w
, H
= mpi
->h
;
123 mp_image_t
*dmpi
=vf_get_image(vf
->next
,mpi
->imgfmt
,
124 MP_IMGTYPE_IP
, MP_IMGFLAG_ACCEPT_STRIDE
|
125 MP_IMGFLAG_PRESERVE
| MP_IMGFLAG_READABLE
,
129 if (!vf
->priv
->pmpi
) vf
->priv
->pmpi
=mpi
;
131 deNoise(mpi
->planes
[0], vf
->priv
->pmpi
->planes
[0], dmpi
->planes
[0],
132 vf
->priv
->Line
, W
, H
,
133 mpi
->stride
[0], vf
->priv
->pmpi
->stride
[0], dmpi
->stride
[0],
134 vf
->priv
->Coefs
[0] + 256,
135 vf
->priv
->Coefs
[0] + 256,
136 vf
->priv
->Coefs
[1] + 256);
137 deNoise(mpi
->planes
[1], vf
->priv
->pmpi
->planes
[1], dmpi
->planes
[1],
138 vf
->priv
->Line
, cw
, ch
,
139 mpi
->stride
[1], vf
->priv
->pmpi
->stride
[1], dmpi
->stride
[1],
140 vf
->priv
->Coefs
[2] + 256,
141 vf
->priv
->Coefs
[2] + 256,
142 vf
->priv
->Coefs
[3] + 256);
143 deNoise(mpi
->planes
[2], vf
->priv
->pmpi
->planes
[2], dmpi
->planes
[2],
144 vf
->priv
->Line
, cw
, ch
,
145 mpi
->stride
[2], vf
->priv
->pmpi
->stride
[2], dmpi
->stride
[2],
146 vf
->priv
->Coefs
[2] + 256,
147 vf
->priv
->Coefs
[2] + 256,
148 vf
->priv
->Coefs
[3] + 256);
150 vf
->priv
->pmpi
=dmpi
; // save reference image
151 return vf_next_put_image(vf
,dmpi
, pts
);
154 //===========================================================================//
156 static int query_format(struct vf_instance_s
* vf
, unsigned int fmt
){
166 return vf_next_query_format(vf
, fmt
);
172 #define ABS(A) ( (A) > 0 ? (A) : -(A) )
174 static void PrecalcCoefs(int *Ct
, double Dist25
)
177 double Gamma
, Simil
, C
;
179 Gamma
= log(0.25) / log(1.0 - Dist25
/255.0);
181 for (i
= -256; i
<= 255; i
++)
183 Simil
= 1.0 - ABS(i
) / 255.0;
184 // Ct[256+i] = lround(pow(Simil, Gamma) * (double)i);
185 C
= pow(Simil
, Gamma
) * (double)i
;
186 Ct
[256+i
] = (C
<0) ? (C
-0.5) : (C
+0.5);
191 static int open(vf_instance_t
*vf
, char* args
){
192 double LumSpac
, LumTmp
, ChromSpac
, ChromTmp
;
193 double Param1
, Param2
, Param3
;
196 vf
->put_image
=put_image
;
197 vf
->query_format
=query_format
;
199 vf
->priv
=malloc(sizeof(struct vf_priv_s
));
200 memset(vf
->priv
, 0, sizeof(struct vf_priv_s
));
204 switch(sscanf(args
, "%lf:%lf:%lf",
205 &Param1
, &Param2
, &Param3
209 LumSpac
= PARAM1_DEFAULT
;
210 LumTmp
= PARAM3_DEFAULT
;
212 ChromSpac
= PARAM2_DEFAULT
;
213 ChromTmp
= LumTmp
* ChromSpac
/ LumSpac
;
218 LumTmp
= PARAM3_DEFAULT
* Param1
/ PARAM1_DEFAULT
;
220 ChromSpac
= PARAM2_DEFAULT
* Param1
/ PARAM1_DEFAULT
;
221 ChromTmp
= LumTmp
* ChromSpac
/ LumSpac
;
226 LumTmp
= PARAM3_DEFAULT
* Param1
/ PARAM1_DEFAULT
;
229 ChromTmp
= LumTmp
* ChromSpac
/ LumSpac
;
237 ChromTmp
= LumTmp
* ChromSpac
/ LumSpac
;
241 LumSpac
= PARAM1_DEFAULT
;
242 LumTmp
= PARAM3_DEFAULT
;
244 ChromSpac
= PARAM2_DEFAULT
;
245 ChromTmp
= LumTmp
* ChromSpac
/ LumSpac
;
250 LumSpac
= PARAM1_DEFAULT
;
251 LumTmp
= PARAM3_DEFAULT
;
253 ChromSpac
= PARAM2_DEFAULT
;
254 ChromTmp
= LumTmp
* ChromSpac
/ LumSpac
;
257 PrecalcCoefs(vf
->priv
->Coefs
[0], LumSpac
);
258 PrecalcCoefs(vf
->priv
->Coefs
[1], LumTmp
);
259 PrecalcCoefs(vf
->priv
->Coefs
[2], ChromSpac
);
260 PrecalcCoefs(vf
->priv
->Coefs
[3], ChromTmp
);
265 const vf_info_t vf_info_denoise3d
= {
266 "3D Denoiser (variable lowpass filter)",
274 //===========================================================================//