2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
14 void vp8_ssim_parms_16x16_c
22 unsigned long *sum_sq_s
,
23 unsigned long *sum_sq_r
,
24 unsigned long *sum_sxr
28 for(i
=0;i
<16;i
++,s
+=sp
,r
+=rp
)
34 *sum_sq_s
+= s
[j
] * s
[j
];
35 *sum_sq_r
+= r
[j
] * r
[j
];
36 *sum_sxr
+= s
[j
] * r
[j
];
40 void vp8_ssim_parms_8x8_c
48 unsigned long *sum_sq_s
,
49 unsigned long *sum_sq_r
,
50 unsigned long *sum_sxr
54 for(i
=0;i
<8;i
++,s
+=sp
,r
+=rp
)
60 *sum_sq_s
+= s
[j
] * s
[j
];
61 *sum_sq_r
+= r
[j
] * r
[j
];
62 *sum_sxr
+= s
[j
] * r
[j
];
67 const static int64_t cc1
= 26634; // (64^2*(.01*255)^2
68 const static int64_t cc2
= 239708; // (64^2*(.03*255)^2
70 static double similarity
74 unsigned long sum_sq_s
,
75 unsigned long sum_sq_r
,
76 unsigned long sum_sxr
,
80 int64_t ssim_n
, ssim_d
;
83 //scale the constants by number of pixels
84 c1
= (cc1
*count
*count
)>>12;
85 c2
= (cc2
*count
*count
)>>12;
87 ssim_n
= (2*sum_s
*sum_r
+ c1
)*((int64_t) 2*count
*sum_sxr
-
88 (int64_t) 2*sum_s
*sum_r
+c2
);
90 ssim_d
= (sum_s
*sum_s
+sum_r
*sum_r
+c1
)*
91 ((int64_t)count
*sum_sq_s
-(int64_t)sum_s
*sum_s
+
92 (int64_t)count
*sum_sq_r
-(int64_t) sum_r
*sum_r
+c2
) ;
94 return ssim_n
* 1.0 / ssim_d
;
97 static double ssim_16x16(unsigned char *s
,int sp
, unsigned char *r
,int rp
,
98 const vp8_variance_rtcd_vtable_t
*rtcd
)
100 unsigned long sum_s
=0,sum_r
=0,sum_sq_s
=0,sum_sq_r
=0,sum_sxr
=0;
101 SSIMPF_INVOKE(rtcd
,16x16
)(s
, sp
, r
, rp
, &sum_s
, &sum_r
, &sum_sq_s
, &sum_sq_r
, &sum_sxr
);
102 return similarity(sum_s
, sum_r
, sum_sq_s
, sum_sq_r
, sum_sxr
, 256);
104 static double ssim_8x8(unsigned char *s
,int sp
, unsigned char *r
,int rp
,
105 const vp8_variance_rtcd_vtable_t
*rtcd
)
107 unsigned long sum_s
=0,sum_r
=0,sum_sq_s
=0,sum_sq_r
=0,sum_sxr
=0;
108 SSIMPF_INVOKE(rtcd
,8x8
)(s
, sp
, r
, rp
, &sum_s
, &sum_r
, &sum_sq_s
, &sum_sq_r
, &sum_sxr
);
109 return similarity(sum_s
, sum_r
, sum_sq_s
, sum_sq_r
, sum_sxr
, 64);
112 // TODO: (jbb) tried to scale this function such that we may be able to use it
113 // for distortion metric in mode selection code ( provided we do a reconstruction)
114 long dssim(unsigned char *s
,int sp
, unsigned char *r
,int rp
,
115 const vp8_variance_rtcd_vtable_t
*rtcd
)
117 unsigned long sum_s
=0,sum_r
=0,sum_sq_s
=0,sum_sq_r
=0,sum_sxr
=0;
119 int64_t ssim_n1
,ssim_n2
;
120 int64_t ssim_d1
,ssim_d2
;
121 int64_t ssim_t1
,ssim_t2
;
124 // normalize by 256/64
128 SSIMPF_INVOKE(rtcd
,16x16
)(s
, sp
, r
, rp
, &sum_s
, &sum_r
, &sum_sq_s
, &sum_sq_r
, &sum_sxr
);
129 ssim_n1
= (2*sum_s
*sum_r
+ c1
);
131 ssim_n2
=((int64_t) 2*256*sum_sxr
-(int64_t) 2*sum_s
*sum_r
+c2
);
133 ssim_d1
=((int64_t)sum_s
*sum_s
+(int64_t)sum_r
*sum_r
+c1
);
135 ssim_d2
= (256 * (int64_t) sum_sq_s
-(int64_t) sum_s
*sum_s
+
136 (int64_t) 256*sum_sq_r
-(int64_t) sum_r
*sum_r
+c2
) ;
138 ssim_t1
= 256 - 256 * ssim_n1
/ ssim_d1
;
139 ssim_t2
= 256 - 256 * ssim_n2
/ ssim_d2
;
141 ssim3
= 256 *ssim_t1
* ssim_t2
;
144 return (long)( ssim3
);
147 // We are using a 8x8 moving window with starting location of each 8x8 window
148 // on the 4x4 pixel grid. Such arrangement allows the windows to overlap
149 // block boundaries to penalize blocking artifacts.
158 const vp8_variance_rtcd_vtable_t
*rtcd
165 // sample point start with each 4x4 location
166 for(i
=0; i
< height
-8; i
+=4, img1
+= stride_img1
*4, img2
+= stride_img2
*4)
168 for(j
=0; j
< width
-8; j
+=4 )
170 double v
= ssim_8x8(img1
+j
, stride_img1
, img2
+j
, stride_img2
, rtcd
);
175 ssim_total
/= samples
;
180 YV12_BUFFER_CONFIG
*source
,
181 YV12_BUFFER_CONFIG
*dest
,
184 const vp8_variance_rtcd_vtable_t
*rtcd
190 a
= vp8_ssim2(source
->y_buffer
, dest
->y_buffer
,
191 source
->y_stride
, dest
->y_stride
, source
->y_width
,
192 source
->y_height
, rtcd
);
194 b
= vp8_ssim2(source
->u_buffer
, dest
->u_buffer
,
195 source
->uv_stride
, dest
->uv_stride
, source
->uv_width
,
196 source
->uv_height
, rtcd
);
198 c
= vp8_ssim2(source
->v_buffer
, dest
->v_buffer
,
199 source
->uv_stride
, dest
->uv_stride
, source
->uv_width
,
200 source
->uv_height
, rtcd
);
202 ssimv
= a
* .8 + .1 * (b
+ c
);
209 double vp8_calc_ssimg
211 YV12_BUFFER_CONFIG
*source
,
212 YV12_BUFFER_CONFIG
*dest
,
216 const vp8_variance_rtcd_vtable_t
*rtcd
222 a
= vp8_ssim2(source
->y_buffer
, dest
->y_buffer
,
223 source
->y_stride
, dest
->y_stride
, source
->y_width
,
224 source
->y_height
, rtcd
);
226 b
= vp8_ssim2(source
->u_buffer
, dest
->u_buffer
,
227 source
->uv_stride
, dest
->uv_stride
, source
->uv_width
,
228 source
->uv_height
, rtcd
);
230 c
= vp8_ssim2(source
->v_buffer
, dest
->v_buffer
,
231 source
->uv_stride
, dest
->uv_stride
, source
->uv_width
,
232 source
->uv_height
, rtcd
);
236 ssim_all
= (a
* 4 + b
+ c
) /6;