]> git.sesse.net Git - narabu/commitdiff
Change quantization to MPEG-2, some other changes.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 16 Sep 2017 13:03:21 +0000 (15:03 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 16 Sep 2017 13:58:08 +0000 (15:58 +0200)
qdc.cpp

diff --git a/qdc.cpp b/qdc.cpp
index 1af42d2d94b79be478b4702871b2a176d7c96500..a0aaf002888cc1b9044dcf09d90cf68de1ef50a7 100644 (file)
--- a/qdc.cpp
+++ b/qdc.cpp
@@ -32,15 +32,17 @@ static const unsigned char std_luminance_quant_tbl[64] = {
        24,  35,  55,  64,  81, 104, 113,  92,
        49,  64,  78,  87, 103, 121, 120, 101,
        72,  92,  95,  98, 112, 100, 103,  99
+#else
+       // ff_mpeg1_default_intra_matrix
+         8, 16, 19, 22, 26, 27, 29, 34,
+        16, 16, 22, 24, 27, 29, 34, 37,                                                 
+        19, 22, 26, 27, 29, 34, 34, 38,                                                 
+        22, 22, 26, 27, 29, 34, 37, 40,
+        22, 26, 27, 29, 32, 35, 40, 48,
+        26, 27, 29, 32, 35, 40, 48, 58,
+        26, 27, 29, 34, 38, 46, 56, 69,
+        27, 29, 35, 38, 46, 56, 69, 83
 #endif
-    16, 16, 19, 22, 26, 27, 29, 34,
-    16, 16, 22, 24, 27, 29, 34, 37,
-    19, 22, 26, 27, 29, 34, 34, 38,
-    22, 22, 26, 27, 29, 34, 37, 40,
-    22, 26, 27, 29, 32, 35, 40, 48,
-    26, 27, 29, 32, 35, 40, 48, 58,
-    26, 27, 29, 34, 38, 46, 56, 69,
-    27, 29, 35, 38, 46, 56, 69, 83
 };
 
 struct SymbolStats
@@ -141,7 +143,7 @@ int pick_stats_for(int y, int x)
        return std::min<int>(x + y, 7);
        //if (x + y >= 7) return 7;
        //return x + y;
-//     return y * 8 + x;
+       //return y * 8 + x;
 #if 0
        if (y == 0 && x == 0) {
                return 0;
@@ -173,11 +175,11 @@ public:
                clear();
        }
 
-       void init_prob(const SymbolStats &s)
+       void init_prob(const SymbolStats &s1, const SymbolStats &s2)
        {
                for (int i = 0; i < NUM_SYMS; i++) {
                        //printf("%d: cumfreqs=%d freqs=%d prob_bits=%d\n", i, s.cum_freqs[i], s.freqs[i], prob_bits);
-                       RansEncSymbolInit(&esyms[i], s.cum_freqs[i], s.freqs[i], prob_bits);
+                       RansEncSymbolInit(&esyms[i], s1.cum_freqs[i], s1.freqs[i], prob_bits);
                }
        }
 
@@ -260,6 +262,38 @@ private:
        RansEncSymbol esyms[NUM_SYMS];
 };
 
+static constexpr int dc_scalefac = 8;  // Matches the FDCT's gain.
+static constexpr double quant_scalefac = 4.0;  // whatever?
+
+static inline int quantize(int f, int coeff_idx)
+{
+       if (coeff_idx == 0) {
+               return f / dc_scalefac;
+       }
+       if (f == 0) {
+               return 0;
+       }
+
+       const int w = std_luminance_quant_tbl[coeff_idx];
+       const int s = quant_scalefac;
+       int sign_f = (f > 0) ? 1 : -1;
+       return (32 * f + sign_f * w * s) / (2 * w * s);
+}
+
+static inline int unquantize(int qf, int coeff_idx)
+{
+       if (coeff_idx == 0) {
+               return qf * dc_scalefac;
+       }
+       if (qf == 0) {
+               return 0;
+       }
+
+       const int w = std_luminance_quant_tbl[coeff_idx];
+       const int s = quant_scalefac;
+       return (2 * qf * w * s) / 32;
+}
+
 int main(void)
 {
        FILE *fp = fopen("pic.pgm", "rb");
@@ -281,48 +315,14 @@ int main(void)
                        // FDCT it
                        fdct_int32(in);
 
-                       //constexpr int extra_deadzone = 64;
-                       constexpr int extra_deadzone = 4;
-
                        for (unsigned y = 0; y < 8; ++y) {
                                for (unsigned x = 0; x < 8; ++x) {
-                                       short *c = &in[y * 8 + x];
-                                       *c <<= 3;
-                                       *c = copysign(std::max(abs(*c) - extra_deadzone, 0), *c);
-                                       //*c /= std_luminance_quant_tbl[y * 8 + x];
-                                       *c = (int)(double(*c) / std_luminance_quant_tbl[y * 8 + x]);
-#if 0
-                                       if (x != 0 || y != 0) {
-                                               int ss = 1;
-                                               if (::abs(int(*c)) <= ss) {
-                                                       *c = 0; // eeh
-                                               } else if (*c > 0) {
-                                                       *c -= ss;  // eeh
-                                               } else {
-                                                       *c += ss;  // eeh
-                                               }
-                                       }
-#endif
-                               }
-                       }
+                                       int coeff_idx = y * 8 + x;
+                                       int k = quantize(in[coeff_idx], coeff_idx);
+                                       coeff[(yb + y) * WIDTH + (xb + x)] = k;
 
-                       // Store it
-                       for (unsigned y = 0; y < 8; ++y) {
-                               for (unsigned x = 0; x < 8; ++x) {
-                                       coeff[(yb + y) * WIDTH + (xb + x)] = in[y * 8 + x];
-                               }
-                       }
-
-                       // and back
-                       for (unsigned y = 0; y < 8; ++y) {
-                               for (unsigned x = 0; x < 8; ++x) {
-                                       in[y * 8 + x] *= std_luminance_quant_tbl[y * 8 + x];
-                                       if (in[y * 8 + x] > 0) {
-                                               in[y * 8 + x] += extra_deadzone;
-                                       } else if (in[y * 8 + x] < 0) {
-                                               in[y * 8 + x] -= extra_deadzone;
-                                       }
-                                       in[y * 8 + x] >>= 3;
+                                       // Store back for reconstruction / PSNR calculation
+                                       in[coeff_idx] = unquantize(k, coeff_idx);
                                }
                        }
 
@@ -412,7 +412,7 @@ int main(void)
 #else
                // TODO: rather gamma-k or something
                for (unsigned j = 0; j < NUM_SYMS; ++j) {
-               //      write_varint(stats[i].freqs[j], codedfp);
+                       write_varint(stats[i].freqs[j], codedfp);
                }
 #endif
        }
@@ -422,9 +422,10 @@ int main(void)
        size_t tot_bytes = 0;
        for (unsigned y = 0; y < 8; ++y) {
                for (unsigned x = 0; x < 8; ++x) {
-                       SymbolStats &s = stats[pick_stats_for(x, y)];
+                       SymbolStats &s1 = stats[pick_stats_for(x, y)];
+                       SymbolStats &s2 = stats[pick_stats_for(x, y) + 8];
 
-                       rans_encoder.init_prob(s);
+                       rans_encoder.init_prob(s1, s2);
 
                        // need to reverse later
                        rans_encoder.clear();