Merge "Skip computation of distortion in vp8_pick_inter_mode if active_map is used"
[libvpx.git] / vp8 / encoder / ssim.c
blobd0f8e490a4512c28799a4b31dad9df0cd58845da
1 /*
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.
9 */
12 #include "onyx_int.h"
14 void vp8_ssim_parms_16x16_c
16 unsigned char *s,
17 int sp,
18 unsigned char *r,
19 int rp,
20 unsigned long *sum_s,
21 unsigned long *sum_r,
22 unsigned long *sum_sq_s,
23 unsigned long *sum_sq_r,
24 unsigned long *sum_sxr
27 int i,j;
28 for(i=0;i<16;i++,s+=sp,r+=rp)
30 for(j=0;j<16;j++)
32 *sum_s += s[j];
33 *sum_r += r[j];
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
42 unsigned char *s,
43 int sp,
44 unsigned char *r,
45 int rp,
46 unsigned long *sum_s,
47 unsigned long *sum_r,
48 unsigned long *sum_sq_s,
49 unsigned long *sum_sq_r,
50 unsigned long *sum_sxr
53 int i,j;
54 for(i=0;i<8;i++,s+=sp,r+=rp)
56 for(j=0;j<8;j++)
58 *sum_s += s[j];
59 *sum_r += r[j];
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
72 unsigned long sum_s,
73 unsigned long sum_r,
74 unsigned long sum_sq_s,
75 unsigned long sum_sq_r,
76 unsigned long sum_sxr,
77 int count
80 int64_t ssim_n, ssim_d;
81 int64_t c1, c2;
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;
118 int64_t ssim3;
119 int64_t ssim_n1,ssim_n2;
120 int64_t ssim_d1,ssim_d2;
121 int64_t ssim_t1,ssim_t2;
122 int64_t c1, c2;
124 // normalize by 256/64
125 c1 = cc1*16;
126 c2 = cc2*16;
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;
142 if(ssim3 <0 )
143 ssim3=0;
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.
150 double vp8_ssim2
152 unsigned char *img1,
153 unsigned char *img2,
154 int stride_img1,
155 int stride_img2,
156 int width,
157 int height,
158 const vp8_variance_rtcd_vtable_t *rtcd
161 int i,j;
162 int samples =0;
163 double ssim_total=0;
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);
171 ssim_total += v;
172 samples++;
175 ssim_total /= samples;
176 return ssim_total;
178 double vp8_calc_ssim
180 YV12_BUFFER_CONFIG *source,
181 YV12_BUFFER_CONFIG *dest,
182 int lumamask,
183 double *weight,
184 const vp8_variance_rtcd_vtable_t *rtcd
187 double a, b, c;
188 double ssimv;
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);
204 *weight = 1;
206 return ssimv;
209 double vp8_calc_ssimg
211 YV12_BUFFER_CONFIG *source,
212 YV12_BUFFER_CONFIG *dest,
213 double *ssim_y,
214 double *ssim_u,
215 double *ssim_v,
216 const vp8_variance_rtcd_vtable_t *rtcd
219 double ssim_all = 0;
220 double a, b, c;
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);
233 *ssim_y = a;
234 *ssim_u = b;
235 *ssim_v = c;
236 ssim_all = (a * 4 + b + c) /6;
238 return ssim_all;