tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

blockiness.c (4505B)


      1 /*
      2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
      3 *
      4 * This source code is subject to the terms of the BSD 2 Clause License and
      5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
      6 * was not distributed with this source code in the LICENSE file, you can
      7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
      8 * Media Patent License 1.0 was not distributed with this source code in the
      9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
     10 */
     11 
     12 #include "av1/encoder/blockiness.h"
     13 
     14 #include <stdint.h>
     15 #include <stdlib.h>
     16 
     17 static int horizontal_filter(const uint8_t *s) {
     18  return (s[1] - s[-2]) * 2 + (s[-1] - s[0]) * 6;
     19 }
     20 
     21 static int vertical_filter(const uint8_t *s, int p) {
     22  return (s[p] - s[-2 * p]) * 2 + (s[-p] - s[0]) * 6;
     23 }
     24 
     25 static int variance(int sum, int sum_squared, int size) {
     26  return sum_squared / size - (sum / size) * (sum / size);
     27 }
     28 // Calculate a blockiness level for a vertical block edge.
     29 // This function returns a new blockiness metric that's defined as
     30 
     31 //              p0 p1 p2 p3
     32 //              q0 q1 q2 q3
     33 // block edge ->
     34 //              r0 r1 r2 r3
     35 //              s0 s1 s2 s3
     36 
     37 // blockiness =  p0*-2+q0*6+r0*-6+s0*2 +
     38 //               p1*-2+q1*6+r1*-6+s1*2 +
     39 //               p2*-2+q2*6+r2*-6+s2*2 +
     40 //               p3*-2+q3*6+r3*-6+s3*2 ;
     41 
     42 // reconstructed_blockiness = abs(blockiness from reconstructed buffer -
     43 //                                blockiness from source buffer,0)
     44 //
     45 // I make the assumption that flat blocks are much more visible than high
     46 // contrast blocks. As such, I scale the result of the blockiness calc
     47 // by dividing the blockiness by the variance of the pixels on either side
     48 // of the edge as follows:
     49 // var_0 = (q0^2+q1^2+q2^2+q3^2) - ((q0 + q1 + q2 + q3) / 4 )^2
     50 // var_1 = (r0^2+r1^2+r2^2+r3^2) - ((r0 + r1 + r2 + r3) / 4 )^2
     51 // The returned blockiness is the scaled value
     52 // Reconstructed blockiness / ( 1 + var_0 + var_1 ) ;
     53 static int blockiness_vertical(const uint8_t *s, int sp, const uint8_t *r,
     54                               int rp, int size) {
     55  int s_blockiness = 0;
     56  int r_blockiness = 0;
     57  int sum_0 = 0;
     58  int sum_sq_0 = 0;
     59  int sum_1 = 0;
     60  int sum_sq_1 = 0;
     61  int i;
     62  int var_0;
     63  int var_1;
     64  for (i = 0; i < size; ++i, s += sp, r += rp) {
     65    s_blockiness += horizontal_filter(s);
     66    r_blockiness += horizontal_filter(r);
     67    sum_0 += s[0];
     68    sum_sq_0 += s[0] * s[0];
     69    sum_1 += s[-1];
     70    sum_sq_1 += s[-1] * s[-1];
     71  }
     72  var_0 = variance(sum_0, sum_sq_0, size);
     73  var_1 = variance(sum_1, sum_sq_1, size);
     74  r_blockiness = abs(r_blockiness);
     75  s_blockiness = abs(s_blockiness);
     76 
     77  if (r_blockiness > s_blockiness)
     78    return (r_blockiness - s_blockiness) / (1 + var_0 + var_1);
     79  else
     80    return 0;
     81 }
     82 
     83 // Calculate a blockiness level for a horizontal block edge
     84 // same as above.
     85 static int blockiness_horizontal(const uint8_t *s, int sp, const uint8_t *r,
     86                                 int rp, int size) {
     87  int s_blockiness = 0;
     88  int r_blockiness = 0;
     89  int sum_0 = 0;
     90  int sum_sq_0 = 0;
     91  int sum_1 = 0;
     92  int sum_sq_1 = 0;
     93  int i;
     94  int var_0;
     95  int var_1;
     96  for (i = 0; i < size; ++i, ++s, ++r) {
     97    s_blockiness += vertical_filter(s, sp);
     98    r_blockiness += vertical_filter(r, rp);
     99    sum_0 += s[0];
    100    sum_sq_0 += s[0] * s[0];
    101    sum_1 += s[-sp];
    102    sum_sq_1 += s[-sp] * s[-sp];
    103  }
    104  var_0 = variance(sum_0, sum_sq_0, size);
    105  var_1 = variance(sum_1, sum_sq_1, size);
    106  r_blockiness = abs(r_blockiness);
    107  s_blockiness = abs(s_blockiness);
    108 
    109  if (r_blockiness > s_blockiness)
    110    return (r_blockiness - s_blockiness) / (1 + var_0 + var_1);
    111  else
    112    return 0;
    113 }
    114 
    115 // This function returns the blockiness for the entire frame currently by
    116 // looking at all borders in steps of 4.
    117 double av1_get_blockiness(const unsigned char *img1, int img1_pitch,
    118                          const unsigned char *img2, int img2_pitch, int width,
    119                          int height) {
    120  double blockiness = 0;
    121  int i, j;
    122  for (i = 0; i < height;
    123       i += 4, img1 += img1_pitch * 4, img2 += img2_pitch * 4) {
    124    for (j = 0; j < width; j += 4) {
    125      if (i > 0 && i < height && j > 0 && j < width) {
    126        blockiness +=
    127            blockiness_vertical(img1 + j, img1_pitch, img2 + j, img2_pitch, 4);
    128        blockiness += blockiness_horizontal(img1 + j, img1_pitch, img2 + j,
    129                                            img2_pitch, 4);
    130      }
    131    }
    132  }
    133  blockiness /= width * height / 16;
    134  return blockiness;
    135 }