Beispiel #1
0
  private int computeCSFDeltaAvg(
      int[] src, int[] dst, int x0, int y0, int w, int h, int channelIdx) {
    final int[] csf;
    final int[] mask_csf;

    if (channelIdx == 0) {
      csf = CSF_Y_1024;
      mask_csf = MASK_CSF_Y_1024;
    } else if (channelIdx == 1) {
      csf = CSF_Cb_1024;
      mask_csf = MASK_CSF_Cb_1024;
    } else {
      csf = CSF_Cr_1024;
      mask_csf = MASK_CSF_Cr_1024;
    }

    long lsum = 0;
    final int[] dct_s = new int[64];
    final int[] dct_d = new int[64];
    int pixels = 0;
    final DCT8 dct = new DCT8();
    IndexedIntArray iia_s = new IndexedIntArray(dct_s, 0);
    IndexedIntArray iia_d = new IndexedIntArray(dct_d, 0);
    int[] s_means_64 = new int[4];
    int[] d_means_64 = new int[4];
    int[] s_vars_1024 = new int[4];
    int[] d_vars_1024 = new int[4];
    final int st = this.stride << this.downSampling;
    final int inc = 1 << this.downSampling;
    final int inc7 = 7 * inc;

    for (int y = y0; y < h - 7; y += inc7) {
      for (int x = x0; x < w - 7; x += inc7) {
        s_means_64[0] = s_means_64[1] = s_means_64[2] = s_means_64[3] = 0;
        d_means_64[0] = d_means_64[1] = d_means_64[2] = d_means_64[3] = 0;
        s_vars_1024[0] = s_vars_1024[1] = s_vars_1024[2] = s_vars_1024[3] = 0;
        d_vars_1024[0] = d_vars_1024[1] = d_vars_1024[2] = d_vars_1024[3] = 0;
        int s_gmean64 = 0;
        int d_gmean64 = 0;
        int s_gvar64 = 0;
        int d_gvar64 = 0;

        // Populate DCT arrays
        for (int i = 0; i < 8; i++) {
          final int i8 = i << 3;
          final int offs = (y + i) * st + (x * inc);

          for (int j = 0; j < 8; j++) {
            final int idx1 = i8 + j;
            final int idx2 = offs + (j * inc);
            final int sub = ((i & 12) >> 2) + ((j & 12) >> 1);
            dct_s[idx1] = src[idx2];
            dct_d[idx1] = dst[idx2];
            s_gmean64 += dct_s[idx1];
            d_gmean64 += dct_d[idx1];
            s_means_64[sub] += (dct_s[idx1] << 2);
            d_means_64[sub] += (dct_d[idx1] << 2);
          }
        }

        // Compute variance
        for (int i = 0; i < 8; i++) {
          final int i8 = i << 3;

          for (int j = 0; j < 8; j++) {
            final int s = dct_s[i8 + j] << 6;
            final int d = dct_d[i8 + j] << 6;
            final int sub = ((i & 12) >> 2) + ((j & 12) >> 1);
            s_gvar64 += (s - s_gmean64) * (s - s_gmean64);
            d_gvar64 += (d - d_gmean64) * (d - d_gmean64);
            s_vars_1024[sub] += (s - s_means_64[sub]) * (s - s_means_64[sub]);
            d_vars_1024[sub] += (d - d_means_64[sub]) * (d - d_means_64[sub]);
          }
        }

        // Replace s_gvar64 /= (63*64) and s_vars_1024[i] *= 16/15 with 63*64*16/15 = 275251/64
        // Since s_vars_1024[i] is scaled by 4 (s_means_1024 scaled by 64*64 instead of 1024),
        // use rescaling factor 275251/256.
        if (s_gvar64 > 0) {
          long sum = (long) (s_vars_1024[0] + s_vars_1024[1] + s_vars_1024[2] + s_vars_1024[3]);
          s_gvar64 = (int) (sum / 256 * 275251 / s_gvar64);
        }

        if (d_gvar64 > 0) {
          long sum = (long) (d_vars_1024[0] + d_vars_1024[1] + d_vars_1024[2] + d_vars_1024[3]);
          d_gvar64 = (int) (sum / 256 * 275251 / d_gvar64);
        }

        // Perform forward DCT (gain is 1<<5)
        iia_s.index = 0;
        dct.forward(iia_s, iia_s);
        iia_d.index = 0;
        dct.forward(iia_d, iia_d);

        // Offset DCT gain
        dct_s[0] >>= 5;
        dct_d[0] >>= 5;

        long s_mask_1024 = 0;
        long d_mask_1024 = 0;

        // Compute masks
        for (int i = 0; i < 8; i++) {
          final int i8 = i << 3;
          final int j0 = (i == 0) ? 1 : 0;

          for (int j = j0; j < 8; j++) {
            final int idx = i8 + j;

            // Offset DCT gain
            dct_s[idx] >>= 5;
            dct_d[idx] >>= 5;
            s_mask_1024 += (dct_s[idx] * dct_s[idx] * mask_csf[idx]);
            d_mask_1024 += (dct_d[idx] * dct_d[idx] * mask_csf[idx]);
          }
        }

        if (d_mask_1024 * d_gvar64 > s_mask_1024 * s_gvar64)
          s_mask_1024 =
              (long) (Global.sqrt((int) d_mask_1024) >> 8) * (long) (Global.sqrt(d_gvar64) >> 7);
        else
          s_mask_1024 =
              (long) (Global.sqrt((int) s_mask_1024) >> 8) * (long) (Global.sqrt(s_gvar64) >> 7);

        // Calculate error
        for (int i = 0; i < 8; i++) {
          final int i8 = i << 3;

          for (int j = 0; j < 8; j++) {
            final int idx = i8 + j;
            long err1024 = ((long) Math.abs(dct_s[idx] - dct_d[idx])) << 10;

            if ((i != 0) || (j != 0))
              err1024 =
                  (err1024 * mask_csf[idx] < s_mask_1024)
                      ? 0
                      : err1024 - (s_mask_1024 / mask_csf[idx]);

            final long val1024 = (err1024 * csf[idx] + 512) >> 10;
            lsum += ((val1024 * val1024) >> 10);
            pixels++;
          }
        }
      }
    }

    return (pixels == 0) ? 0 : (int) (((lsum + 512) >> 10) / pixels);
  }