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.
27 #define PARAM1_DEFAULT 4.0
28 #define PARAM2_DEFAULT 3.0
29 #define PARAM3_DEFAULT 6.0
31 //===========================================================================//
36 unsigned short *Frame
[3];
40 /***************************************************************************/
42 static /*inline*/ unsigned int LowPassMul(unsigned int PrevMul
, unsigned int CurrMul
, int* Coef
){
43 // int dMul= (PrevMul&0xFFFFFF)-(CurrMul&0xFFFFFF);
44 int dMul
= PrevMul
-CurrMul
;
45 unsigned int d
=((dMul
+0x10007FF)>>12);
46 return CurrMul
+ Coef
[d
];
49 static void deNoiseTemporal(
50 unsigned char *Frame
, // mpi->planes[x]
51 unsigned char *FrameDest
, // dmpi->planes[x]
52 unsigned short *FrameAnt
,
53 int W
, int H
, int sStride
, int dStride
,
56 unsigned int PixelDst
;
58 for (long Y
= 0; Y
< H
; Y
++){
59 for (long X
= 0; X
< W
; X
++){
60 PixelDst
= LowPassMul(FrameAnt
[X
]<<8, Frame
[X
]<<16, Temporal
);
61 FrameAnt
[X
] = ((PixelDst
+0x1000007F)>>8);
62 FrameDest
[X
]= ((PixelDst
+0x10007FFF)>>16);
70 static void deNoiseSpacial(
71 unsigned char *Frame
, // mpi->planes[x]
72 unsigned char *FrameDest
, // dmpi->planes[x]
73 unsigned int *LineAnt
, // vf->priv->Line (width bytes)
74 int W
, int H
, int sStride
, int dStride
,
75 int *Horizontal
, int *Vertical
)
77 long sLineOffs
= 0, dLineOffs
= 0;
78 unsigned int PixelAnt
;
79 unsigned int PixelDst
;
81 /* First pixel has no left nor top neighbor. */
82 PixelDst
= LineAnt
[0] = PixelAnt
= Frame
[0]<<16;
83 FrameDest
[0]= ((PixelDst
+0x10007FFF)>>16);
85 /* First line has no top neighbor, only left. */
86 for (long X
= 1; X
< W
; X
++){
87 PixelDst
= LineAnt
[X
] = LowPassMul(PixelAnt
, Frame
[X
]<<16, Horizontal
);
88 FrameDest
[X
]= ((PixelDst
+0x10007FFF)>>16);
91 for (long Y
= 1; Y
< H
; Y
++){
92 unsigned int PixelAnt
;
93 sLineOffs
+= sStride
, dLineOffs
+= dStride
;
94 /* First pixel on each line doesn't have previous pixel */
95 PixelAnt
= Frame
[sLineOffs
]<<16;
96 PixelDst
= LineAnt
[0] = LowPassMul(LineAnt
[0], PixelAnt
, Vertical
);
97 FrameDest
[dLineOffs
]= ((PixelDst
+0x10007FFF)>>16);
99 for (long X
= 1; X
< W
; X
++){
100 unsigned int PixelDst
;
101 /* The rest are normal */
102 PixelAnt
= LowPassMul(PixelAnt
, Frame
[sLineOffs
+X
]<<16, Horizontal
);
103 PixelDst
= LineAnt
[X
] = LowPassMul(LineAnt
[X
], PixelAnt
, Vertical
);
104 FrameDest
[dLineOffs
+X
]= ((PixelDst
+0x10007FFF)>>16);
109 static void deNoise(unsigned char *Frame
, // mpi->planes[x]
110 unsigned char *FrameDest
, // dmpi->planes[x]
111 unsigned int *LineAnt
, // vf->priv->Line (width bytes)
112 unsigned short **FrameAntPtr
,
113 int W
, int H
, int sStride
, int dStride
,
114 int *Horizontal
, int *Vertical
, int *Temporal
)
116 long sLineOffs
= 0, dLineOffs
= 0;
117 unsigned int PixelAnt
;
118 unsigned int PixelDst
;
119 unsigned short* FrameAnt
=(*FrameAntPtr
);
122 (*FrameAntPtr
)=FrameAnt
=malloc(W
*H
*sizeof(unsigned short));
125 for (long Y
= 0; Y
< H
; Y
++){
126 unsigned short* dst
=&FrameAnt
[Y
*W
];
127 unsigned char* src
=Frame
+Y
*sStride
;
128 for (long X
= 0; X
< W
; X
++) dst
[X
]=src
[X
]<<8;
132 if(!Horizontal
[0] && !Vertical
[0]){
133 deNoiseTemporal(Frame
, FrameDest
, FrameAnt
,
134 W
, H
, sStride
, dStride
, Temporal
);
138 deNoiseSpacial(Frame
, FrameDest
, LineAnt
,
139 W
, H
, sStride
, dStride
, Horizontal
, Vertical
);
143 /* First pixel has no left nor top neighbor. Only previous frame */
144 LineAnt
[0] = PixelAnt
= Frame
[0]<<16;
145 PixelDst
= LowPassMul(FrameAnt
[0]<<8, PixelAnt
, Temporal
);
146 FrameAnt
[0] = ((PixelDst
+0x1000007F)>>8);
147 FrameDest
[0]= ((PixelDst
+0x10007FFF)>>16);
149 /* First line has no top neighbor. Only left one for each pixel and
151 for (long X
= 1; X
< W
; X
++){
152 LineAnt
[X
] = PixelAnt
= LowPassMul(PixelAnt
, Frame
[X
]<<16, Horizontal
);
153 PixelDst
= LowPassMul(FrameAnt
[X
]<<8, PixelAnt
, Temporal
);
154 FrameAnt
[X
] = ((PixelDst
+0x1000007F)>>8);
155 FrameDest
[X
]= ((PixelDst
+0x10007FFF)>>16);
158 for (long Y
= 1; Y
< H
; Y
++){
159 unsigned int PixelAnt
;
160 unsigned short* LinePrev
=&FrameAnt
[Y
*W
];
161 sLineOffs
+= sStride
, dLineOffs
+= dStride
;
162 /* First pixel on each line doesn't have previous pixel */
163 PixelAnt
= Frame
[sLineOffs
]<<16;
164 LineAnt
[0] = LowPassMul(LineAnt
[0], PixelAnt
, Vertical
);
165 PixelDst
= LowPassMul(LinePrev
[0]<<8, LineAnt
[0], Temporal
);
166 LinePrev
[0] = ((PixelDst
+0x1000007F)>>8);
167 FrameDest
[dLineOffs
]= ((PixelDst
+0x10007FFF)>>16);
169 for (long X
= 1; X
< W
; X
++){
170 unsigned int PixelDst
;
171 /* The rest are normal */
172 PixelAnt
= LowPassMul(PixelAnt
, Frame
[sLineOffs
+X
]<<16, Horizontal
);
173 LineAnt
[X
] = LowPassMul(LineAnt
[X
], PixelAnt
, Vertical
);
174 PixelDst
= LowPassMul(LinePrev
[X
]<<8, LineAnt
[X
], Temporal
);
175 LinePrev
[X
] = ((PixelDst
+0x1000007F)>>8);
176 FrameDest
[dLineOffs
+X
]= ((PixelDst
+0x10007FFF)>>16);
182 //===========================================================================//
184 static void PrecalcCoefs(int *Ct
, double Dist25
)
186 double Gamma
, Simil
, C
;
188 Gamma
= log(0.25) / log(1.0 - Dist25
/255.0 - 0.00001);
190 for (int i
= -255*16; i
<= 255*16; i
++)
192 Simil
= 1.0 - abs(i
) / (16*255.0);
193 C
= pow(Simil
, Gamma
) * 65536.0 * (double)i
/ 16.0;
194 Ct
[16*256+i
] = (C
<0) ? (C
-0.5) : (C
+0.5);
197 Ct
[0] = (Dist25
!= 0);
201 //===========================================================================//