📄 tinyjpeg.c
字号:
{ const unsigned char *y; unsigned char *p; unsigned int i; p = priv->plane[0]; y = priv->Y; for (i=0; i<8; i++) { memcpy(p, y, 16); y += 16; p += priv->width; }}/** * YCrCb -> Grey (1x2) * .---. * | 1 | * |---| * | 2 | * `---' */static void YCrCB_to_Grey_1x2(struct jdec_private *priv){ const unsigned char *y; unsigned char *p; unsigned int i; p = priv->plane[0]; y = priv->Y; for (i=0; i<16; i++) { memcpy(p, y, 8); y += 8; p += priv->width; }}/** * YCrCb -> Grey (2x2) * .-------. * | 1 | 2 | * |---+---| * | 3 | 4 | * `-------' */static void YCrCB_to_Grey_2x2(struct jdec_private *priv){ const unsigned char *y; unsigned char *p; unsigned int i; p = priv->plane[0]; y = priv->Y; for (i=0; i<16; i++) { memcpy(p, y, 16); y += 16; p += priv->width; }}/* * Decode all the 3 components for 1x1 */static void decode_MCU_1x1_3planes(struct jdec_private *priv){ // Y process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y, 8); // Cb process_Huffman_data_unit(priv, cCb); IDCT(&priv->component_infos[cCb], priv->Cb, 8); // Cr process_Huffman_data_unit(priv, cCr); IDCT(&priv->component_infos[cCr], priv->Cr, 8);}/* * Decode a 1x1 directly in 1 color */static void decode_MCU_1x1_1plane(struct jdec_private *priv){ // Y process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y, 8); // Cb process_Huffman_data_unit(priv, cCb); IDCT(&priv->component_infos[cCb], priv->Cb, 8); // Cr process_Huffman_data_unit(priv, cCr); IDCT(&priv->component_infos[cCr], priv->Cr, 8);}/* * Decode a 2x1 * .-------. * | 1 | 2 | * `-------' */static void decode_MCU_2x1_3planes(struct jdec_private *priv){ // Y process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y, 16); process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y+8, 16); // Cb process_Huffman_data_unit(priv, cCb); IDCT(&priv->component_infos[cCb], priv->Cb, 8); // Cr process_Huffman_data_unit(priv, cCr); IDCT(&priv->component_infos[cCr], priv->Cr, 8);}static void pixart_decode_MCU_2x1_3planes(struct jdec_private *priv){ unsigned char marker; pixart_look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, 8, marker); /* 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 within the range below, if it gets out of this range we're most likely decoding garbage */ if (marker < 0x20 || marker > 0x7f) { snprintf(priv->error_string, sizeof(priv->error_string), "Pixart JPEG error: invalid MCU marker: 0x%02x\n", (unsigned int)marker); longjmp(priv->jump_state, -EIO); } skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, 8); // Y pixart_process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y, 16); pixart_process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y+8, 16); // Cb pixart_process_Huffman_data_unit(priv, cCb); IDCT(&priv->component_infos[cCb], priv->Cb, 8); // Cr pixart_process_Huffman_data_unit(priv, cCr); IDCT(&priv->component_infos[cCr], priv->Cr, 8);}/* * Decode a 2x1 * .-------. * | 1 | 2 | * `-------' */static void decode_MCU_2x1_1plane(struct jdec_private *priv){ // Y process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y, 16); process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y+8, 16); // Cb process_Huffman_data_unit(priv, cCb); // Cr process_Huffman_data_unit(priv, cCr);}/* * Decode a 2x2 * .-------. * | 1 | 2 | * |---+---| * | 3 | 4 | * `-------' */static void decode_MCU_2x2_3planes(struct jdec_private *priv){ // Y process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y, 16); process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y+8, 16); process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y+64*2, 16); process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y+64*2+8, 16); // Cb process_Huffman_data_unit(priv, cCb); IDCT(&priv->component_infos[cCb], priv->Cb, 8); // Cr process_Huffman_data_unit(priv, cCr); IDCT(&priv->component_infos[cCr], priv->Cr, 8);}/* * Decode a 2x2 directly in GREY format (8bits) * .-------. * | 1 | 2 | * |---+---| * | 3 | 4 | * `-------' */static void decode_MCU_2x2_1plane(struct jdec_private *priv){ // Y process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y, 16); process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y+8, 16); process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y+64*2, 16); process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y+64*2+8, 16); // Cb process_Huffman_data_unit(priv, cCb); // Cr process_Huffman_data_unit(priv, cCr);}/* * Decode a 1x2 mcu * .---. * | 1 | * |---| * | 2 | * `---' */static void decode_MCU_1x2_3planes(struct jdec_private *priv){ // Y process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y, 8); process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y+64, 8); // Cb process_Huffman_data_unit(priv, cCb); IDCT(&priv->component_infos[cCb], priv->Cb, 8); // Cr process_Huffman_data_unit(priv, cCr); IDCT(&priv->component_infos[cCr], priv->Cr, 8);}/* * Decode a 1x2 mcu * .---. * | 1 | * |---| * | 2 | * `---' */static void decode_MCU_1x2_1plane(struct jdec_private *priv){ // Y process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y, 8); process_Huffman_data_unit(priv, cY); IDCT(&priv->component_infos[cY], priv->Y+64, 8); // Cb process_Huffman_data_unit(priv, cCb); // Cr process_Huffman_data_unit(priv, cCr);}static void print_SOF(const unsigned char *stream){ int width, height, nr_components, precision;#if DEBUG const char *nr_components_to_string[] = { "????", "Grayscale", "????", "YCbCr", "CYMK" };#endif precision = stream[2]; height = be16_to_cpu(stream+3); width = be16_to_cpu(stream+5); nr_components = stream[7]; trace("> SOF marker\n"); trace("Size:%dx%d nr_components:%d (%s) precision:%d\n", width, height, nr_components, nr_components_to_string[nr_components], precision);}/******************************************************************************* * * JPEG/JFIF Parsing functions * * Note: only a small subset of the jpeg file format is supported. No markers, * nor progressive stream is supported. * ******************************************************************************/static void build_quantization_table(float *qtable, const unsigned char *ref_table){ /* Taken from libjpeg. Copyright Independent JPEG Group's LLM idct. * For float AA&N IDCT method, divisors are equal to quantization * coefficients scaled by scalefactor[row]*scalefactor[col], where * scalefactor[0] = 1 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 * We apply a further scale factor of 8. * What's actually stored is 1/divisor so that the inner loop can * use a multiplication rather than a division. */ int i, j; static const double aanscalefactor[8] = { 1.0, 1.387039845, 1.306562965, 1.175875602, 1.0, 0.785694958, 0.541196100, 0.275899379 }; const unsigned char *zz = zigzag; for (i=0; i<8; i++) { for (j=0; j<8; j++) { *qtable++ = ref_table[*zz++] * aanscalefactor[i] * aanscalefactor[j]; } }}static int parse_DQT(struct jdec_private *priv, const unsigned char *stream){ int qi; float *table; const unsigned char *dqt_block_end; trace("> DQT marker\n"); dqt_block_end = stream + be16_to_cpu(stream); stream += 2; /* Skip length */ while (stream < dqt_block_end) { qi = *stream++;#if SANITY_CHECK if (qi>>4) error("16 bits quantization table is not supported\n"); if (qi >= COMPONENTS) error("No more than %d quantization tables supported (got %d)\n", COMPONENTS, qi + 1);#endif table = priv->Q_tables[qi]; build_quantization_table(table, stream); stream += 64; } trace("< DQT marker\n"); return 0;}static int parse_SOF(struct jdec_private *priv, const unsigned char *stream){ int i, width, height, nr_components, cid, sampling_factor; int Q_table; struct component *c; trace("> SOF marker\n"); print_SOF(stream); height = be16_to_cpu(stream+3); width = be16_to_cpu(stream+5); nr_components = stream[7];#if SANITY_CHECK if (stream[2] != 8) error("Precision other than 8 is not supported\n"); if (width>JPEG_MAX_WIDTH || height>JPEG_MAX_HEIGHT) error("Width and Height (%dx%d) seems suspicious\n", width, height); if (nr_components != 3) error("We only support YUV images\n"); if (height%8) error("Height need to be a multiple of 8 (current height is %d)\n", height); if (width%16) error("Width need to be a multiple of 16 (current Width is %d)\n", width);#endif stream += 8; for (i=0; i<nr_components; i++) { cid = *stream++; sampling_factor = *stream++; Q_table = *stream++; c = &priv->component_infos[i];#if SANITY_CHECK c->cid = cid;#endif c->Vfactor = sampling_factor&0xf; c->Hfactor = sampling_factor>>4; c->Q_table = priv->Q_tables[Q_table]; trace("Component:%d factor:%dx%d Quantization table:%d\n", cid, c->Hfactor, c->Hfactor, Q_table ); } priv->width = width; priv->height = height; trace("< SOF marker\n"); return 0;}static int parse_SOS(struct jdec_private *priv, const unsigned char *stream){ unsigned int i, cid, table; unsigned int nr_components = stream[2]; trace("> SOS marker\n");#if SANITY_CHECK if (nr_components != 3) error("We only support YCbCr image\n");#endif stream += 3; for (i=0;i<nr_components;i++) { cid = *stream++; table = *stream++;#if SANITY_CHECK if ((table&0xf) >= HUFFMAN_TABLES) error("We do not support more than %d AC Huffman table\n", HUFFMAN_TABLES); if ((table>>4) >= HUFFMAN_TABLES) error("We do not support more than %d DC Huffman table\n", HUFFMAN_TABLES); if (cid != priv->component_infos[i].cid) error("SOS cid order (%u:%u) isn't compatible with the SOF marker (%u:%u)\n", i, cid, i, priv->component_infos[i].cid); trace("ComponentId:%u tableAC:%d tableDC:%d\n", cid, table&0xf, table>>4);#endif priv->component_infos[i].AC_table = &priv->HTAC[table&0xf]; priv->component_infos[i].DC_table = &priv->HTDC[table>>4]; } priv->stream = stream+3; /* ITU-T T.81 (9/92) chapter E.1.3 clearly states that RSTm is to be set to 0 at the beginning of each scan */ priv->last_rst_marker_seen = 0; trace("< SOS marker\n"); return 0;}static int parse_DHT(struct jdec_private *priv, const unsigned char *stream){ unsigned int count, i; unsigned char huff_bits[17]; int length, index; length = be16_to_cpu(stream) - 2; stream += 2; /* Skip length */ trace("> DHT marker (length=%d)\n", length); while (length>0) { index = *stream++; /* We need to calculate the number of bytes 'vals' will takes */ huff_bits[0] = 0; count = 0; for (i=1; i<17; i++) { huff_bits[i] = *stream++; count += huff_bits[i]; }#if SANITY_CHECK if (count > 1024) error("No more than 1024 bytes is allowed to describe a huffman table\n"); if ( (index &0xf) >= HUFFMAN_TABLES) error("No mode than %d Huffman tables is supported\n", HUFFMAN_TABLES); trace("Huffman table %s n%d\n", (index&0xf0)?"AC":"DC", index&0xf);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -