Ejemplo n.º 1
0
        /// <summary>
        /// Save away a copy of the Q-table referenced by each component present
        /// in the current scan, unless already saved during a prior scan.
        ///
        /// In a multiple-scan JPEG file, the encoder could assign different components
        /// the same Q-table slot number, but change table definitions between scans
        /// so that each component uses a different Q-table.  (The IJG encoder is not
        /// currently capable of doing this, but other encoders might.)  Since we want
        /// to be able to dequantize all the components at the end of the file, this
        /// means that we have to save away the table actually used for each component.
        /// We do this by copying the table at the start of the first scan containing
        /// the component.
        /// The JPEG spec prohibits the encoder from changing the contents of a Q-table
        /// slot between scans of a component using that slot.  If the encoder does so
        /// anyway, this decoder will simply use the Q-table values that were current
        /// at the start of the first scan for the component.
        ///
        /// The decompressor output side looks only at the saved quant tables,
        /// not at the current Q-table slots.
        /// </summary>
        private void latch_quant_tables()
        {
            for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
            {
                jpeg_component_info componentInfo = m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[ci]];

                /* No work if we already saved Q-table for this component */
                if (componentInfo.quant_table != null)
                {
                    continue;
                }

                /* Make sure specified quantization table is present */
                int qtblno = componentInfo.Quant_tbl_no;
                if (qtblno < 0 || qtblno >= JpegConstants.NUM_QUANT_TBLS || m_cinfo.m_quant_tbl_ptrs[qtblno] == null)
                {
                    m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_NO_QUANT_TABLE, qtblno);
                }

                /* OK, save away the quantization table */
                JQUANT_TBL qtbl = new JQUANT_TBL();
                Buffer.BlockCopy(m_cinfo.m_quant_tbl_ptrs[qtblno].quantval, 0,
                                 qtbl.quantval, 0, qtbl.quantval.Length * sizeof(short));
                qtbl.Sent_table           = m_cinfo.m_quant_tbl_ptrs[qtblno].Sent_table;
                componentInfo.quant_table = qtbl;
                m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[ci]] = componentInfo;
            }
        }
Ejemplo n.º 2
0
        // Save away a copy of the Q-table referenced by each component present
        // in the current scan, unless already saved during a prior scan.
        //
        // In a multiple-scan JPEG file, the encoder could assign different components
        // the same Q-table slot number, but change table definitions between scans
        // so that each component uses a different Q-table. (The IJG encoder is not
        // currently capable of doing this, but other encoders might.) Since we want
        // to be able to dequantize all the components at the end of the file, this
        // means that we have to save away the table actually used for each component.
        // We do this by copying the table at the start of the first scan containing
        // the component.
        // The JPEG spec prohibits the encoder from changing the contents of a Q-table
        // slot between scans of a component using that slot. If the encoder does so
        // anyway, this decoder will simply use the Q-table values that were current
        // at the start of the first scan for the component.
        //
        // The decompressor output side looks only at the saved quant tables,
        // not at the current Q-table slots.
        static void latch_quant_tables_lossy(jpeg_decompress cinfo)
        {
            for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
            {
                jpeg_component_info compptr = cinfo.cur_comp_info[ci];
                // No work if we already saved Q-table for this component
                if (compptr.quant_table != null)
                {
                    continue;
                }

                // Make sure specified quantization table is present
                int qtblno = compptr.quant_tbl_no;
                if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || cinfo.quant_tbl_ptrs[qtblno] == null)
                {
                    ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_NO_QUANT_TABLE, qtblno);
                }

                // OK, save away the quantization table
                JQUANT_TBL qtbl = new JQUANT_TBL();

                cinfo.quant_tbl_ptrs[qtblno].quantval.CopyTo(qtbl.quantval, 0);
                qtbl.sent_table = cinfo.quant_tbl_ptrs[qtblno].sent_table;

                compptr.quant_table = qtbl;
            }
        }
Ejemplo n.º 3
0
		// Routines to write specific marker types.

		// Emit a DQT marker
		// Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking
		static int emit_dqt(jpeg_compress cinfo, int index)
		{
			JQUANT_TBL qtbl=cinfo.quant_tbl_ptrs[index];
			if(qtbl==null) ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_NO_QUANT_TABLE, index);

			int prec=0;
			for(int i=0; i<DCTSIZE2; i++)
			{
				if(qtbl.quantval[i]>255) prec=1;
			}

			if(!qtbl.sent_table)
			{
				emit_marker(cinfo, JPEG_MARKER.M_DQT);

				emit_2bytes(cinfo, prec!=0?DCTSIZE2*2+1+2:DCTSIZE2+1+2);

				emit_byte(cinfo, index+(prec<<4));

				for(int i=0; i<DCTSIZE2; i++)
				{
					// The table entries must be emitted in zigzag order.
					uint qval=qtbl.quantval[jpeg_natural_order[i]];
					if(prec!=0) emit_byte(cinfo, (int)(qval>>8));
					emit_byte(cinfo, (int)(qval&0xFF));
				}

				qtbl.sent_table=true;
			}

			return prec;
		}
        /// <summary>
        /// Determine whether block smoothing is applicable and safe.
        /// We also latch the current states of the coef_bits[] entries for the
        /// AC coefficients; otherwise, if the input side of the decompressor
        /// advances into a new scan, we might think the coefficients are known
        /// more accurately than they really are.
        /// </summary>
        private bool smoothing_ok()
        {
            if (!m_cinfo.m_progressive_mode || m_cinfo.m_coef_bits == null)
            {
                return(false);
            }

            /* Allocate latch area if not already done */
            if (m_coef_bits_latch == null)
            {
                m_coef_bits_latch       = new int[m_cinfo.m_num_components * SAVED_COEFS];
                m_coef_bits_savedOffset = 0;
            }

            bool smoothing_useful = false;

            for (int ci = 0; ci < m_cinfo.m_num_components; ci++)
            {
                /* All components' quantization values must already be latched. */
                JQUANT_TBL qtable = m_cinfo.Comp_info[ci].quant_table;
                if (qtable == null)
                {
                    return(false);
                }

                /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */
                if (qtable.quantval[0] == 0 || qtable.quantval[Q01_POS] == 0 ||
                    qtable.quantval[Q10_POS] == 0 || qtable.quantval[Q20_POS] == 0 ||
                    qtable.quantval[Q11_POS] == 0 || qtable.quantval[Q02_POS] == 0)
                {
                    return(false);
                }

                /* DC values must be at least partly known for all components. */
                if (m_cinfo.m_coef_bits[ci][0] < 0)
                {
                    return(false);
                }

                /* Block smoothing is helpful if some AC coefficients remain inaccurate. */
                for (int coefi = 1; coefi <= 5; coefi++)
                {
                    m_coef_bits_latch[m_coef_bits_savedOffset + coefi] = m_cinfo.m_coef_bits[ci][coefi];
                    if (m_cinfo.m_coef_bits[ci][coefi] != 0)
                    {
                        smoothing_useful = true;
                    }
                }

                m_coef_bits_savedOffset += SAVED_COEFS;
            }

            return(smoothing_useful);
        }
Ejemplo n.º 5
0
        // Convenience routines for allocating quantization and Huffman tables.
        // (Would jutils.cs be a more reasonable place to put these?)
        public static JQUANT_TBL jpeg_alloc_quant_table(jpeg_common cinfo)
        {
            JQUANT_TBL tbl = null;

            try
            {
                tbl            = new JQUANT_TBL();
                tbl.sent_table = false;                 // make sure this is false in any new table
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }

            return(tbl);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Emit a DQT marker
        /// </summary>
        /// <param name="index">The index.</param>
        /// <returns>the precision used (0 = 8bits, 1 = 16bits) for baseline checking</returns>
        private int emit_dqt(int index)
        {
            JQUANT_TBL qtbl = m_cinfo.m_quant_tbl_ptrs[index];

            if (qtbl == null)
            {
                m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_NO_QUANT_TABLE, index);
            }

            int prec = 0;

            for (int i = 0; i <= m_cinfo.lim_Se; i++)
            {
                if (qtbl.quantval[m_cinfo.natural_order[i]] > 255)
                {
                    prec = 1;
                }
            }

            if (!qtbl.Sent_table)
            {
                emit_marker(JPEG_MARKER.DQT);

                emit_2bytes(prec != 0 ?
                            m_cinfo.lim_Se * 2 + 2 + 1 + 2 : m_cinfo.lim_Se + 1 + 1 + 2);

                emit_byte(index + (prec << 4));

                for (int i = 0; i <= m_cinfo.lim_Se; i++)
                {
                    /* The table entries must be emitted in zigzag order. */
                    int qval = qtbl.quantval[m_cinfo.natural_order[i]];

                    if (prec != 0)
                    {
                        emit_byte(qval >> 8);
                    }

                    emit_byte(qval & 0xFF);
                }

                qtbl.Sent_table = true;
            }

            return(prec);
        }
Ejemplo n.º 7
0
        // Prepare for an output pass.
        // Here we select the proper IDCT routine for each component and build
        // a matching multiplier table.
        static void start_pass_idctmgr(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;
            idct_controller    idct   = (idct_controller)lossyd.idct_private;

            for (int ci = 0; ci < cinfo.num_components; ci++)
            {
                jpeg_component_info compptr = cinfo.comp_info[ci];

                // Select the proper IDCT routine for this component's scaling
                lossyd.inverse_DCT[ci] = jpeg_idct_ifast;

                // Create multiplier table from quant table.
                // However, we can skip this if the component is uninteresting
                // or if we already built the table. Also, if no quant table
                // has yet been saved for the component, we leave the
                // multiplier table all-zero; we'll be reading zeroes from the
                // coefficient controller's buffer anyway.
                if (!compptr.component_needed || idct.cur_method[ci] == JDCT_IFAST)
                {
                    continue;
                }

                JQUANT_TBL qtbl = compptr.quant_table;
                if (qtbl == null)
                {
                    continue;                                   // happens if no data yet for component
                }
                idct.cur_method[ci] = JDCT_IFAST;
                // For AA&N IDCT method, multipliers 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
                // For integer operation, the multiplier table is to be scaled by 2.
                int[] ifmtbl = compptr.dct_table;

                for (int i = 0; i < DCTSIZE2; i++)
                {
                    ifmtbl[i] = (((int)qtbl.quantval[i] * aanscales[i]) + (1 << 11)) >> 12;
                }
            }
        }
Ejemplo n.º 8
0
		// Save away a copy of the Q-table referenced by each component present
		// in the current scan, unless already saved during a prior scan.
		//
		// In a multiple-scan JPEG file, the encoder could assign different components
		// the same Q-table slot number, but change table definitions between scans
		// so that each component uses a different Q-table. (The IJG encoder is not
		// currently capable of doing this, but other encoders might.) Since we want
		// to be able to dequantize all the components at the end of the file, this
		// means that we have to save away the table actually used for each component.
		// We do this by copying the table at the start of the first scan containing
		// the component.
		// The JPEG spec prohibits the encoder from changing the contents of a Q-table
		// slot between scans of a component using that slot. If the encoder does so
		// anyway, this decoder will simply use the Q-table values that were current
		// at the start of the first scan for the component.
		//
		// The decompressor output side looks only at the saved quant tables,
		// not at the current Q-table slots.
		static void latch_quant_tables_lossy(jpeg_decompress cinfo)
		{
			for(int ci=0; ci<cinfo.comps_in_scan; ci++)
			{
				jpeg_component_info compptr=cinfo.cur_comp_info[ci];
				// No work if we already saved Q-table for this component
				if(compptr.quant_table!=null) continue;

				// Make sure specified quantization table is present
				int qtblno=compptr.quant_tbl_no;
				if(qtblno<0||qtblno>=NUM_QUANT_TBLS||cinfo.quant_tbl_ptrs[qtblno]==null) ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_NO_QUANT_TABLE, qtblno);

				// OK, save away the quantization table
				JQUANT_TBL qtbl=new JQUANT_TBL();

				cinfo.quant_tbl_ptrs[qtblno].quantval.CopyTo(qtbl.quantval, 0);
				qtbl.sent_table=cinfo.quant_tbl_ptrs[qtblno].sent_table;

				compptr.quant_table=qtbl;
			}
		}
Ejemplo n.º 9
0
 /// <summary>
 /// Save away a copy of the Q-table referenced by each component present
 /// in the current scan, unless already saved during a prior scan.
 /// 
 /// In a multiple-scan JPEG file, the encoder could assign different components
 /// the same Q-table slot number, but change table definitions between scans
 /// so that each component uses a different Q-table.  (The IJG encoder is not
 /// currently capable of doing this, but other encoders might.)  Since we want
 /// to be able to dequantize all the components at the end of the file, this
 /// means that we have to save away the table actually used for each component.
 /// We do this by copying the table at the start of the first scan containing
 /// the component.
 /// The JPEG spec prohibits the encoder from changing the contents of a Q-table
 /// slot between scans of a component using that slot.  If the encoder does so
 /// anyway, this decoder will simply use the Q-table values that were current
 /// at the start of the first scan for the component.
 /// 
 /// The decompressor output side looks only at the saved quant tables,
 /// not at the current Q-table slots.
 /// </summary>
 private void latch_quant_tables()
 {
     for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
     {
         jpeg_component_info componentInfo = m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[ci]];
         
         /* No work if we already saved Q-table for this component */
         if (componentInfo.quant_table != null)
             continue;
         
         /* Make sure specified quantization table is present */
         int qtblno = componentInfo.Quant_tbl_no;
         if (qtblno < 0 || qtblno >= JpegConstants.NUM_QUANT_TBLS || m_cinfo.m_quant_tbl_ptrs[qtblno] == null)
             m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_NO_QUANT_TABLE, qtblno);
         
         /* OK, save away the quantization table */
         JQUANT_TBL qtbl = new JQUANT_TBL();
         Buffer.BlockCopy(m_cinfo.m_quant_tbl_ptrs[qtblno].quantval, 0,
             qtbl.quantval, 0, qtbl.quantval.Length * sizeof(short));
         qtbl.Sent_table = m_cinfo.m_quant_tbl_ptrs[qtblno].Sent_table;
         componentInfo.quant_table = qtbl;
         m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[ci]] = componentInfo;
     }
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Process a DQT marker
        /// </summary>
        private bool get_dqt()
        {
            int length;

            if (!m_cinfo.m_src.GetTwoBytes(out length))
            {
                return(false);
            }

            length -= 2;
            while (length > 0)
            {
                int n;
                if (!m_cinfo.m_src.GetByte(out n))
                {
                    return(false);
                }

                int prec = n >> 4;
                n &= 0x0F;

                m_cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_DQT, n, prec);

                if (n >= JpegConstants.NUM_QUANT_TBLS)
                {
                    m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_DQT_INDEX, n);
                }

                if (m_cinfo.m_quant_tbl_ptrs[n] == null)
                {
                    m_cinfo.m_quant_tbl_ptrs[n] = new JQUANT_TBL();
                }

                JQUANT_TBL quant_ptr = m_cinfo.m_quant_tbl_ptrs[n];

                for (int i = 0; i < JpegConstants.DCTSIZE2; i++)
                {
                    int tmp;
                    if (prec != 0)
                    {
                        int temp = 0;
                        if (!m_cinfo.m_src.GetTwoBytes(out temp))
                        {
                            return(false);
                        }

                        tmp = temp;
                    }
                    else
                    {
                        int temp = 0;
                        if (!m_cinfo.m_src.GetByte(out temp))
                        {
                            return(false);
                        }

                        tmp = temp;
                    }

                    /* We convert the zigzag-order table to natural array order. */
                    quant_ptr.quantval[JpegUtils.jpeg_natural_order[i]] = (short)tmp;
                }

                if (m_cinfo.m_err.m_trace_level >= 2)
                {
                    for (int i = 0; i < JpegConstants.DCTSIZE2; i += 8)
                    {
                        m_cinfo.TRACEMS(2, J_MESSAGE_CODE.JTRC_QUANTVALS, quant_ptr.quantval[i],
                                        quant_ptr.quantval[i + 1], quant_ptr.quantval[i + 2],
                                        quant_ptr.quantval[i + 3], quant_ptr.quantval[i + 4],
                                        quant_ptr.quantval[i + 5], quant_ptr.quantval[i + 6], quant_ptr.quantval[i + 7]);
                    }
                }

                length -= JpegConstants.DCTSIZE2 + 1;
                if (prec != 0)
                {
                    length -= JpegConstants.DCTSIZE2;
                }
            }

            if (length != 0)
            {
                m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_LENGTH);
            }

            return(true);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Initialize for a processing pass.
        /// Verify that all referenced Q-tables are present, and set up
        /// the divisor table for each one.
        /// In the current implementation, DCT of all components is done during
        /// the first pass, even if only some components will be output in the
        /// first scan.  Hence all components should be examined here.
        /// </summary>
        public virtual void start_pass()
        {
            for (int ci = 0; ci < m_cinfo.m_num_components; ci++)
            {
                int qtblno = m_cinfo.Component_info[ci].Quant_tbl_no;

                /* Make sure specified quantization table is present */
                if (qtblno < 0 || qtblno >= JpegConstants.NUM_QUANT_TBLS || m_cinfo.m_quant_tbl_ptrs[qtblno] == null)
                {
                    m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_NO_QUANT_TABLE, qtblno);
                }

                JQUANT_TBL qtbl = m_cinfo.m_quant_tbl_ptrs[qtblno];

                /* Compute divisors for this quant table */
                /* We may do this more than once for same table, but it's not a big deal */
                int i = 0;
                switch (m_cinfo.m_dct_method)
                {
                case J_DCT_METHOD.JDCT_ISLOW:
                    /* For LL&M IDCT method, divisors are equal to raw quantization
                     * coefficients multiplied by 8 (to counteract scaling).
                     */
                    if (m_divisors[qtblno] == null)
                    {
                        m_divisors[qtblno] = new int [JpegConstants.DCTSIZE2];
                    }

                    for (i = 0; i < JpegConstants.DCTSIZE2; i++)
                    {
                        m_divisors[qtblno][i] = ((int)qtbl.quantval[i]) << 3;
                    }

                    break;

                case J_DCT_METHOD.JDCT_IFAST:
                    if (m_divisors[qtblno] == null)
                    {
                        m_divisors[qtblno] = new int [JpegConstants.DCTSIZE2];
                    }

                    for (i = 0; i < JpegConstants.DCTSIZE2; i++)
                    {
                        m_divisors[qtblno][i] = JpegUtils.DESCALE((int)qtbl.quantval[i] * (int)aanscales[i], CONST_BITS - 3);
                    }
                    break;

                case J_DCT_METHOD.JDCT_FLOAT:
                    if (m_float_divisors[qtblno] == null)
                    {
                        m_float_divisors[qtblno] = new float [JpegConstants.DCTSIZE2];
                    }

                    float[] fdtbl = m_float_divisors[qtblno];
                    i = 0;
                    for (int row = 0; row < JpegConstants.DCTSIZE; row++)
                    {
                        for (int col = 0; col < JpegConstants.DCTSIZE; col++)
                        {
                            fdtbl[i] = (float)(1.0 / (((double)qtbl.quantval[i] * aanscalefactor[row] * aanscalefactor[col] * 8.0)));
                            i++;
                        }
                    }
                    break;

                default:
                    m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_NOT_COMPILED);
                    break;
                }
            }
        }
Ejemplo n.º 12
0
        // Variant of decompress_data for use when doing block smoothing.
        static CONSUME_INPUT decompress_smooth_data(jpeg_decompress cinfo, byte[][][] output_buf)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;
            d_coef_controller  coef   = (d_coef_controller)lossyd.coef_private;

            // Force some input to be done if we are getting ahead of the input.
            while (cinfo.input_scan_number <= cinfo.output_scan_number && !cinfo.inputctl.eoi_reached)
            {
                if (cinfo.input_scan_number == cinfo.output_scan_number)
                {
                    // If input is working on current scan, we ordinarily want it to
                    // have completed the current row. But if input scan is DC,
                    // we want it to keep one row ahead so that next block row's DC
                    // values are up to date.
                    uint delta = (cinfo.Ss == 0)?1u:0u;
                    if (cinfo.input_iMCU_row > cinfo.output_iMCU_row + delta)
                    {
                        break;
                    }
                }
                if (cinfo.inputctl.consume_input(cinfo) == CONSUME_INPUT.JPEG_SUSPENDED)
                {
                    return(CONSUME_INPUT.JPEG_SUSPENDED);
                }
            }

            uint last_iMCU_row = cinfo.total_iMCU_rows - 1;

            short[] workspace = new short[DCTSIZE2];

            // OK, output from the arrays.
            for (int ci = 0; ci < cinfo.num_components; ci++)
            {
                jpeg_component_info compptr = cinfo.comp_info[ci];

                // Don't bother to IDCT an uninteresting component.
                if (!compptr.component_needed)
                {
                    continue;
                }

                // Count non-dummy DCT block rows in this iMCU row.
                int  block_rows, access_rows;
                bool last_row;
                if (cinfo.output_iMCU_row < last_iMCU_row)
                {
                    block_rows  = compptr.v_samp_factor;
                    access_rows = block_rows * 2;                 // this and next iMCU row
                    last_row    = false;
                }
                else
                {
                    // NB: can't use last_row_height here; it is input-side-dependent!
                    block_rows = (int)(compptr.height_in_blocks % compptr.v_samp_factor);
                    if (block_rows == 0)
                    {
                        block_rows = compptr.v_samp_factor;
                    }
                    access_rows = block_rows;                   // this iMCU row only
                    last_row    = true;
                }

                // Align the buffer for this component.
                bool        first_row;
                short[][][] buffer;
                int         buffer_ind;
                if (cinfo.output_iMCU_row > 0)
                {
                    access_rows += compptr.v_samp_factor;                              // prior iMCU row too
                    buffer       = coef.whole_image[ci];
                    buffer_ind   = (int)cinfo.output_iMCU_row * compptr.v_samp_factor; // point to current iMCU row
                    first_row    = false;
                }
                else
                {
                    buffer     = coef.whole_image[ci];
                    buffer_ind = 0;
                    first_row  = true;
                }

                // Fetch component-dependent info
                int[]                  coef_bits      = coef.coef_bits_latch[ci];
                JQUANT_TBL             quanttbl       = compptr.quant_table;
                int                    Q00            = quanttbl.quantval[0];
                int                    Q01            = quanttbl.quantval[Q01_POS];
                int                    Q10            = quanttbl.quantval[Q10_POS];
                int                    Q20            = quanttbl.quantval[Q20_POS];
                int                    Q11            = quanttbl.quantval[Q11_POS];
                int                    Q02            = quanttbl.quantval[Q02_POS];
                inverse_DCT_method_ptr inverse_DCT    = lossyd.inverse_DCT[ci];
                uint                   output_buf_ind = 0;

                // Loop over all DCT blocks to be processed.
                for (int block_row = 0; block_row < block_rows; block_row++)
                {
                    short[][] buffer_ptr = buffer[buffer_ind + block_row];
                    short[][] prev_block_row;
                    short[][] next_block_row;

                    if (first_row && block_row == 0)
                    {
                        prev_block_row = buffer_ptr;
                    }
                    else
                    {
                        prev_block_row = buffer[buffer_ind + block_row - 1];
                    }
                    if (last_row && block_row == block_rows - 1)
                    {
                        next_block_row = buffer_ptr;
                    }
                    else
                    {
                        next_block_row = buffer[buffer_ind + block_row + 1];
                    }

                    // We fetch the surrounding DC values using a sliding-register approach.
                    // Initialize all nine here so as to do the right thing on narrow pics.
                    int DC1, DC2, DC3, DC4, DC5, DC6, DC7, DC8, DC9;
                    DC1 = DC2 = DC3 = (int)prev_block_row[0][0];
                    DC4 = DC5 = DC6 = (int)buffer_ptr[0][0];
                    DC7 = DC8 = DC9 = (int)next_block_row[0][0];
                    int ind = 1;

                    uint output_col = 0;

                    uint last_block_column = compptr.width_in_blocks - 1;
                    for (uint block_num = 0; block_num <= last_block_column; block_num++)
                    {
                        // Fetch current DCT block into workspace so we can modify it.
                        buffer_ptr.CopyTo(workspace, 0);

                        // Update DC values
                        if (block_num < last_block_column)
                        {
                            DC3 = (int)prev_block_row[ind][0];
                            DC6 = (int)buffer_ptr[ind][0];
                            DC9 = (int)next_block_row[ind][0];
                        }
                        // Compute coefficient estimates per K.8.
                        // An estimate is applied only if coefficient is still zero,
                        // and is not known to be fully accurate.

                        // AC01
                        int Al = coef_bits[1];
                        if (Al != 0 && workspace[1] == 0)
                        {
                            int num = 36 * Q00 * (DC4 - DC6);
                            int pred;
                            if (num >= 0)
                            {
                                pred = (int)(((Q01 << 7) + num) / (Q01 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                            }
                            else
                            {
                                pred = (int)(((Q01 << 7) - num) / (Q01 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                                pred = -pred;
                            }
                            workspace[1] = (short)pred;
                        }

                        // AC10
                        Al = coef_bits[2];
                        if (Al != 0 && workspace[8] == 0)
                        {
                            int num = 36 * Q00 * (DC2 - DC8);
                            int pred;
                            if (num >= 0)
                            {
                                pred = (int)(((Q10 << 7) + num) / (Q10 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                            }
                            else
                            {
                                pred = (int)(((Q10 << 7) - num) / (Q10 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                                pred = -pred;
                            }
                            workspace[8] = (short)pred;
                        }

                        // AC20
                        Al = coef_bits[3];
                        if (Al != 0 && workspace[16] == 0)
                        {
                            int num = 9 * Q00 * (DC2 + DC8 - 2 * DC5);
                            int pred;
                            if (num >= 0)
                            {
                                pred = (int)(((Q20 << 7) + num) / (Q20 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                            }
                            else
                            {
                                pred = (int)(((Q20 << 7) - num) / (Q20 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                                pred = -pred;
                            }
                            workspace[16] = (short)pred;
                        }

                        // AC11
                        Al = coef_bits[4];
                        if (Al != 0 && workspace[9] == 0)
                        {
                            int num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
                            int pred;
                            if (num >= 0)
                            {
                                pred = (int)(((Q11 << 7) + num) / (Q11 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                            }
                            else
                            {
                                pred = (int)(((Q11 << 7) - num) / (Q11 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                                pred = -pred;
                            }
                            workspace[9] = (short)pred;
                        }

                        // AC02
                        Al = coef_bits[5];
                        if (Al != 0 && workspace[2] == 0)
                        {
                            int num = 9 * Q00 * (DC4 + DC6 - 2 * DC5);
                            int pred;
                            if (num >= 0)
                            {
                                pred = (int)(((Q02 << 7) + num) / (Q02 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                            }
                            else
                            {
                                pred = (int)(((Q02 << 7) - num) / (Q02 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                                pred = -pred;
                            }
                            workspace[2] = (short)pred;
                        }

                        // OK, do the IDCT
                        inverse_DCT(cinfo, compptr, workspace, output_buf[ci], output_buf_ind, output_col);

                        // Advance for next column
                        DC1 = DC2; DC2 = DC3;
                        DC4 = DC5; DC5 = DC6;
                        DC7 = DC8; DC8 = DC9;
                        ind++;
                        output_col += compptr.DCT_scaled_size;
                    }
                    output_buf_ind += compptr.DCT_scaled_size;
                }
            }

            if (++(cinfo.output_iMCU_row) < cinfo.total_iMCU_rows)
            {
                return(CONSUME_INPUT.JPEG_ROW_COMPLETED);
            }
            return(CONSUME_INPUT.JPEG_SCAN_COMPLETED);
        }
Ejemplo n.º 13
0
        // Determine whether block smoothing is applicable and safe.
        // We also latch the current states of the coef_bits[] entries for the
        // AC coefficients; otherwise, if the input side of the decompressor
        // advances into a new scan, we might think the coefficients are known
        // more accurately than they really are.
        static bool smoothing_ok(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;
            d_coef_controller  coef   = (d_coef_controller)lossyd.coef_private;

            if (cinfo.process != J_CODEC_PROCESS.JPROC_PROGRESSIVE || cinfo.coef_bits == null)
            {
                return(false);
            }

            // Allocate latch area if not already done
            if (coef.coef_bits_latch == null)
            {
                try
                {
                    coef.coef_bits_latch = new int[cinfo.num_components][];
                    for (int i = 0; i < cinfo.num_components; i++)
                    {
                        coef.coef_bits_latch[i] = new int[SAVED_COEFS];
                    }
                }
                catch
                {
                    ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
                }
            }

            bool smoothing_useful = false;

            for (int ci = 0; ci < cinfo.num_components; ci++)
            {
                jpeg_component_info compptr = cinfo.comp_info[ci];

                // All components' quantization values must already be latched.
                JQUANT_TBL qtable = compptr.quant_table;
                if (qtable == null)
                {
                    return(false);
                }

                // Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide.
                if (qtable.quantval[0] == 0 || qtable.quantval[Q01_POS] == 0 || qtable.quantval[Q10_POS] == 0 || qtable.quantval[Q20_POS] == 0 || qtable.quantval[Q11_POS] == 0 || qtable.quantval[Q02_POS] == 0)
                {
                    return(false);
                }

                // DC values must be at least partly known for all components.
                int[] coef_bits = cinfo.coef_bits[ci];
                if (coef_bits[0] < 0)
                {
                    return(false);
                }

                // Block smoothing is helpful if some AC coefficients remain inaccurate.
                for (int coefi = 1; coefi <= 5; coefi++)
                {
                    coef.coef_bits_latch[ci][coefi] = coef_bits[coefi];
                    if (coef_bits[coefi] != 0)
                    {
                        smoothing_useful = true;
                    }
                }
            }

            return(smoothing_useful);
        }
Ejemplo n.º 14
0
        // Initialize for a processing pass.
        // Verify that all referenced Q-tables are present, and set up
        // the divisor table for each one.
        // In the current implementation, DCT of all components is done during
        // the first pass, even if only some components will be output in the
        // first scan. Hence all components should be examined here.
        static void start_pass_fdctmgr(jpeg_compress cinfo)
        {
            jpeg_lossy_c_codec lossyc = (jpeg_lossy_c_codec)cinfo.coef;
            fdct_controller    fdct   = (fdct_controller)lossyc.fdct_private;

            for (int ci = 0; ci < cinfo.num_components; ci++)
            {
                jpeg_component_info compptr = cinfo.comp_info[ci];
                int qtblno = compptr.quant_tbl_no;

                // Make sure specified quantization table is present
                if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || cinfo.quant_tbl_ptrs[qtblno] == null)
                {
                    ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_NO_QUANT_TABLE, qtblno);
                }

                JQUANT_TBL qtbl = cinfo.quant_tbl_ptrs[qtblno];

                // Compute divisors for this quant table
                // We may do this more than once for same table, but it's not a big deal
                if (fdct.divisors[qtblno] == null)
                {
                    try
                    {
                        fdct.divisors[qtblno] = new int[DCTSIZE2];
                    }
                    catch
                    {
                        ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
                    }
                }

                int[] dtbl = fdct.divisors[qtblno];
                for (int i = 0; i < DCTSIZE2; i++)
                {
                    dtbl[i] = ((int)qtbl.quantval[i] * aanscales[i] + 1024) >> 11;
                }

#if DCT_FLOAT_SUPPORTED
                if (fdct.float_divisors[qtblno] == null)
                {
                    try
                    {
                        fdct.float_divisors[qtblno] = new double[DCTSIZE2];
                    }
                    catch
                    {
                        ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
                    }
                }

                double[] fdtbl = fdct.float_divisors[qtblno];
                int      di    = 0;
                for (int row = 0; row < DCTSIZE; row++)
                {
                    for (int col = 0; col < DCTSIZE; col++)
                    {
                        fdtbl[di] = 1.0 / (qtbl.quantval[di] * aanscalefactor[row] * aanscalefactor[col] * 8.0);
                        di++;
                    }
                }
#endif
            }
        }