static function computeDCTAndQualityFromImage()

in pdq/php/pdqhasher.php [622:754]


  static function computeDCTAndQualityFromImage(
    /*resource*/&$image,
    /*bool*/ $show_timings,
    /*bool*/ $dump
  ) {
    $num_rows = imagesy($image);
    $num_cols = imagesx($image);
    if ($dump) {
      echo "num_rows=$num_rows\n";
      echo "num_cols=$num_cols\n";
    }

    //  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // RGB to luma
    $t1 = microtime(true);
    $luma_matrix = self::imageToLumaMatrix($image, $num_rows, $num_cols);
    $t2 = microtime(true);
    if ($show_timings) {
      printf("X010-LUMA %.6f\n", $t2-$t1);
    }

    //  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // Downsample (blur and decimate)
    $t1 = microtime(true);
    $window_size_along_rows = self::computeJaroszFilterWindowSize($num_cols);
    $window_size_along_cols = self::computeJaroszFilterWindowSize($num_rows);
    self::jaroszFilter($luma_matrix, $num_rows, $num_cols, $window_size_along_rows, $window_size_along_cols);
    $t2 = microtime(true);
    if ($show_timings) {
      printf("X020-JRSZ %.6f\n", $t2-$t1);
    }

    // Decimation per se. Target centers not corners.
    $buffer_64x64 = array();
    for ($i = 0; $i < 64; $i++) {
      $row = array();
      for ($j = 0; $j < 64; $j++) {
        $row[$j] = 0;
      }
      $buffer_64x64[$i] = $row;
    }
    $t1 = microtime(true);
    for ($i = 0; $i < 64; $i++) {
      $ini = (int)((($i + 0.5) * $num_rows) / 64);
      for ($j = 0; $j < 64; $j++) {
        $inj = (int)((($j + 0.5) * $num_cols) / 64);
        $buffer_64x64[$i][$j] = $luma_matrix[$ini][$inj];
      }
    }
    $t2 = microtime(true);
    if ($dump) {
      echo "DOWNSAMPLE IMAGE:\n";
      print_r($buffer_64x64);
    }
    if ($show_timings) {
      printf("X030-DSMP %.6f\n", $t2-$t1);
    }

    //  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // Quality metric.  Reuse the 64x64 image-domain downsample
    // since we already have it.
    $t1 = microtime(true);
    $quality = self::computeImageDomainQualityMetric($buffer_64x64);
    $t2 = microtime(true);
    if ($show_timings) {
      printf("X040-QMTC %.6f\n", $t2-$t1);
    }
    if ($dump) {
      echo "QUALITY:$quality\n";
    }

    //  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    $t1 = microtime(true);

    $buffer_16x64 = array();
    for ($i = 0; $i < 16; $i++) {
      $row = array();
      for ($j = 0; $j < 64; $j++) {
        $row[$j] = 0;
      }
      $buffer_16x64[$i] = $row;
    }

    $buffer_16x16 = array();
    for ($i = 0; $i < 16; $i++) {
      $row = array();
      for ($j = 0; $j < 16; $j++) {
        $row[$j] = 0;
      }
      $buffer_16x16[$i] = $row;
    }

    $dct_16x64 = array();
    for ($i = 0; $i < 16; $i++) {
      $row = array();
      for ($j = 0; $j < 64; $j++) {
        $row[$j] = 0;
      }
      $dct_16x64[$i] = $row;
    }
    // See comments on dct64To16. Input is (0..63)x(0..63); output is
    // (1..16)x(1..16) with the latter indexed as (0..15)x(0..15).
    $matrix_scale_factor = sqrt(2.0 / 64.0);
    $pi = 3.141592653589793;
    for ($i = 0; $i < 16; $i++) {
      for ($j = 0; $j < 64; $j++) {
        $dct_16x64[$i][$j] = $matrix_scale_factor *
          cos(($pi / 2 / 64.0) * ($i+1) * (2 * $j + 1));
      }
    }
    $t2 = microtime(true);
    if ($show_timings) {
      printf("X050-DMTX %.6f\n", $t2-$t1);
    }
    if ($dump) {
      echo "DCT MATRIX:\n";
      print_r($dct_16x64);
    }

    // 2D DCT
    $t1 = microtime(true);
    self::computeDCT64To16($buffer_64x64, $buffer_16x64, $buffer_16x16, $dct_16x64);
    $t2 = microtime(true);
    if ($show_timings) {
      printf("X060-CDCT %.6f\n", $t2-$t1);
    }
    if ($dump) {
      echo "DCT OUTPUT:\n";
      print_r($buffer_16x16);
    }

    return array($buffer_16x16, $quality);
  }