libv4lconvert: Further Pixart JPEG decompression tweaks
authorHans de Goede <hdegoede@redhat.com>
Fri, 27 Apr 2012 12:56:18 +0000 (14:56 +0200)
committerHans de Goede <hdegoede@redhat.com>
Fri, 27 Apr 2012 12:58:21 +0000 (14:58 +0200)
Many thanks to Jean-François Moine <moinejf@free.fr> for digging the
quantization tables out of the windows driver.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
lib/libv4lconvert/tinyjpeg.c

index 8fc484e..d227c79 100644 (file)
@@ -205,6 +205,7 @@ static const unsigned char val_ac_chrominance[] = {
        0xf9, 0xfa
 };
 
+#if 0 /* unused */
 /* Standard JPEG quantization tables from Annex K of the JPEG standard.
    Note unlike in Annex K the entries here are in zigzag order! */
 const unsigned char standard_quantization[][64] = { {
@@ -228,6 +229,7 @@ const unsigned char standard_quantization[][64] = { {
                0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
        },
 };
+#endif
 
 /*
  * 4 functions to manage the stream
@@ -1402,39 +1404,74 @@ static void pixart_decode_MCU_2x1_3planes(struct jdec_private *priv)
           different quantization table per MCU. So if the marker changes we
           need to rebuild the quantization tables. */
        if (marker != priv->marker) {
-               int i, j, comp;
+               int i, j, comp, lumi, chroma;
                unsigned char qt[64];
                /* These values have been found by trial and error and seem to
                   work reasonably. Markers with index 0 - 7 are never
                   generated by the hardware, so they are likely wrong. */
                const int qfactor[32] = {
-                        10,   12,  14,  16,  18,  20,  22,  24,
                         25,   30,  35,  40,  45,  50,  55,  60,
-                        64,   68,  80,  90, 100, 120, 140, 160,
-                       180,  200, 220, 240, 260, 280, 300, 320
+                        65,   70,  75,  80,  85,  90,  95, 100,
+                       100,  100, 120, 140, 160, 180, 210, 240,
+                       270,  300, 330, 360, 390, 420, 450, 480
                };
+               /* These tables were found in SPC230NC.SYS */
+               const unsigned char pixart_q[][64] = { {
+                       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+                       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+                       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+                       0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10,
+                       0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+                       0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+                       0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20,
+                       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+               }, {
+                       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10,
+                       0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+                       0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+                       0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20,
+                       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+                       0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40,
+                       0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+                       0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+               }, {
+                       0x08, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x10, 0x10,
+                       0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+                       0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20,
+                       0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40,
+                       0x40, 0x40, 0x40, 0x40, 0x63, 0x63, 0x63, 0x63,
+                       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+                       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+                       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+               }, {
+                       0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20,
+                       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63,
+                       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+                       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+                       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+                       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+                       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+                       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+               } };
 
                i = (marker & 0x7c) >> 2; /* Bits 0 and 1 are always 0 */
                comp = qfactor[i];
+               lumi = (marker & 0x40) ? 1 : 0;
+               chroma = (marker & 0x80) ? 2 : 3;
+               /* printf("marker %02x comp %d lumi %d chroma %d\n", marker, comp, lumi, chroma); */
 
-               /* And another special Pixart feature, the DC quantization
-                  factor is fixed! */
-               qt[0] = 7; 
+               /* Note the DC quantization factor is fixed! */
+               qt[0] = pixart_q[lumi][0]; 
                for (i = 1; i < 64; i++) {
-                       j = (standard_quantization[0][i] * comp + 50) / 100;
+                       j = (pixart_q[lumi][i] * comp + 50) / 100;
                        qt[i] = (j < 255) ? j : 255;
                }
                build_quantization_table(priv->Q_tables[0], qt);
 
-               /* And yet another Pixart JPEG special feature, Pixart JPEG
-                  uses the luminance table for chrominance too! Either
-                  as is or with all values multiplied by 2, this is encoded
-                  in bit 7 of the marker. */
-               if (!(marker & 0x80)) {
-                       for (i = 0; i < 64; i++) {
-                               j = qt[i] * 2;
-                               qt[i] = (j < 255) ? j : 255;
-                       }
+               qt[0] = pixart_q[chroma][0]; 
+               for (i = 1; i < 64; i++) {
+                       j = (pixart_q[chroma][i] * comp + 50) / 100;
+                       qt[i] = (j < 255) ? j : 255;
                }
                build_quantization_table(priv->Q_tables[1], qt);