@@ -103,6 +103,7 @@ struct jdec_private {
#if SANITY_CHECK
unsigned int current_cid; /* For planar JPEG */
#endif
+ unsigned char marker; /* for PJPG (Pixart JPEG) */
/* Temp space used after the IDCT to store each components */
uint8_t Y[64 * 4], Cr[64], Cb[64];
@@ -1376,6 +1376,8 @@ static void decode_MCU_2x1_3planes(struct jdec_private *priv)
IDCT(&priv->component_infos[cCr], priv->Cr, 8);
}
+static void build_quantization_table(float *qtable, const unsigned char *ref_table);
+
static void pixart_decode_MCU_2x1_3planes(struct jdec_private *priv)
{
unsigned char marker;
@@ -1384,10 +1386,8 @@ static void pixart_decode_MCU_2x1_3planes(struct jdec_private *priv)
/* I think the marker indicates which quantization table to use, iow
a Pixart JPEG may have a different quantization table per MCU, most
MCU's have 0x44 as marker for which our special Pixart quantization
- tables are correct. Unfortunately with a 7302 some blocks also have 0x48,
- and sometimes even other values. As 0x48 is quite common too, we really
- need to find out the correct table for that, as currently the blocks
- with a 0x48 marker look wrong. During normal operation the marker stays
+ tables are correct. [jfm: snip]
+ During normal operation the marker stays
within the range below, if it gets out of this range we're most likely
decoding garbage */
if (marker < 0x20 || marker > 0x7f) {
@@ -1396,6 +1396,53 @@ static void pixart_decode_MCU_2x1_3planes(struct jdec_private *priv)
(unsigned int)marker);
longjmp(priv->jump_state, -EIO);
}
+
+ /* rebuild the Y quantization table when the marker changes */
+ if (marker != priv->marker) {
+ unsigned char quant_new[64];
+ int i, j;
+ /*
+ * table to rebuild the Y quantization table
+ * index 1 = marker / 4
+ * index 2 = 4 end indexes in the quantization table
+ * values = 0x08, 0x10, 0x20, 0x40, 0x63
+ * jfm: The values have been guessed from 4 images, so,
+ * better values may be found...
+ */
+ static const unsigned char q_tb[12][4] = {
+ { 6, 28, 43, 64 }, /* 68 */
+ { 6, 24, 40, 60 },
+ { 4, 18, 30, 55 },
+ { 2, 10, 20, 50 }, /* 80 */
+ { 1, 6, 15, 46 },
+ { 1, 4, 15, 37 },
+ { 1, 3, 15, 30 },
+ { 1, 2, 15, 21 },
+ { 1, 1, 15, 18 }, /* 100 */
+ { 1, 1, 15, 16 },
+ { 1, 1, 15, 15 },
+ { 1, 1, 10, 10 },
+ };
+
+ priv->marker = marker;
+ j = marker - 68;
+ if (j < 0)
+ j = 0;
+ j >>= 2;
+ if (j > sizeof q_tb / sizeof q_tb[0])
+ j = sizeof q_tb / sizeof q_tb[0] - 1;
+ for (i = 0; i < q_tb[j][0]; i++)
+ quant_new[i] = 0x08;
+ for (; i < q_tb[j][1]; i++)
+ quant_new[i] = 0x10;
+ for (; i < q_tb[j][2]; i++)
+ quant_new[i] = 0x20;
+ for (; i < q_tb[j][3]; i++)
+ quant_new[i] = 0x40;
+ for (; i < 64; i++)
+ quant_new[i] = 0x63;
+ build_quantization_table(priv->Q_tables[0], quant_new);
+ }
skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, 8);
// Y
@@ -1948,6 +1995,7 @@ static int parse_JFIF(struct jdec_private *priv, const unsigned char *stream)
if (!priv->default_huffman_table_initialized) {
build_quantization_table(priv->Q_tables[0], pixart_quantization[0]);
build_quantization_table(priv->Q_tables[1], pixart_quantization[1]);
+ priv->marker = 68; /* common starting marker */
}
}