/// <summary>
        /// Reset within-iMCU-row counters for a new row (input side)
        /// </summary>
        private void start_iMCU_row()
        {
            /* In an interleaved scan, an MCU row is the same as an iMCU row.
             * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
             * But at the bottom of the image, process only what's left.
             */
            if (m_cinfo.m_comps_in_scan > 1)
            {
                m_MCU_rows_per_iMCU_row = 1;
            }
            else
            {
                jpeg_component_info componentInfo = m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[0]];

                if (m_cinfo.m_input_iMCU_row < (m_cinfo.m_total_iMCU_rows - 1))
                {
                    m_MCU_rows_per_iMCU_row = componentInfo.V_samp_factor;
                }
                else
                {
                    m_MCU_rows_per_iMCU_row = componentInfo.last_row_height;
                }
            }

            m_MCU_ctr         = 0;
            m_MCU_vert_offset = 0;
        }
Example #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;
            }
        }
        /// <summary>
        /// Downsample pixel values of a single component.
        /// This version handles the standard case of 2:1 horizontal and 2:1 vertical,
        /// without smoothing.
        /// </summary>
        private void h2v2_downsample(int componentIndex, byte[][] input_data, int startInputRow, byte[][] output_data, int startOutRow)
        {
            /* Expand input data enough to let all the output samples be generated
             * by the standard loop.  Special-casing padded output would be more
             * efficient.
             */
            jpeg_component_info compptr = m_cinfo.Component_info[componentIndex];
            int output_cols             = compptr.Width_in_blocks * compptr.DCT_h_scaled_size;

            expand_right_edge(input_data, startInputRow, m_cinfo.m_max_v_samp_factor, m_cinfo.m_image_width, output_cols * 2);

            int inrow  = 0;
            int outrow = 0;

            while (inrow < m_cinfo.m_max_v_samp_factor)
            {
                /* bias = 1,2,1,2,... for successive samples */
                int bias        = 1;
                int inputColumn = 0;
                for (int outcol = 0; outcol < output_cols; outcol++)
                {
                    output_data[startOutRow + outrow][outcol] = (byte)((
                                                                           (int)input_data[startInputRow + inrow][inputColumn] +
                                                                           (int)input_data[startInputRow + inrow][inputColumn + 1] +
                                                                           (int)input_data[startInputRow + inrow + 1][inputColumn] +
                                                                           (int)input_data[startInputRow + inrow + 1][inputColumn + 1] + bias) >> 2);

                    bias        ^= 3; /* 1=>2, 2=>1 */
                    inputColumn += 2;
                }

                inrow += 2;
                outrow++;
            }
        }
Example #4
0
        // Initialize IDCT manager.
        static void jinit_inverse_dct(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;
            idct_controller    idct   = null;

            try
            {
                idct = new idct_controller();
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }

            lossyd.idct_private    = idct;
            lossyd.idct_start_pass = start_pass_idctmgr;

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

                // Allocate and pre-zero a multiplier table for each component
                try
                {
                    compptr.dct_table = new int[DCTSIZE2];
                }
                catch
                {
                    ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
                }

                // Mark multiplier table not yet set up for any method
                idct.cur_method[ci] = -1;
            }
        }
Example #5
0
        //////////////////////////////////////////////////////////////////////////
        // Routines to write specific marker types.
        //

        /// <summary>
        /// Emit a SOS marker
        /// </summary>
        private void emit_sos()
        {
            emit_marker(JPEG_MARKER.SOS);

            emit_2bytes(2 * m_cinfo.m_comps_in_scan + 2 + 1 + 3); /* length */

            emit_byte(m_cinfo.m_comps_in_scan);

            for (int i = 0; i < m_cinfo.m_comps_in_scan; i++)
            {
                int componentIndex          = m_cinfo.m_cur_comp_info[i];
                jpeg_component_info compptr = m_cinfo.Component_info[componentIndex];
                emit_byte(compptr.Component_id);

                /* We emit 0 for unused field(s); this is recommended by the P&M text
                 * but does not seem to be specified in the standard.
                 */

                /* DC needs no table for refinement scan */
                int td = (m_cinfo.m_Ss == 0 && m_cinfo.m_Ah == 0) ? compptr.Dc_tbl_no : 0;

                /* AC needs no table when not present */
                int ta = (m_cinfo.m_Se != 0) ? compptr.Ac_tbl_no : 0;

                emit_byte((td << 4) + ta);
            }

            emit_byte(m_cinfo.m_Ss);
            emit_byte(m_cinfo.m_Se);
            emit_byte((m_cinfo.m_Ah << 4) + m_cinfo.m_Al);
        }
Example #6
0
        /// <summary>
        /// Emit a SOF marker
        /// </summary>
        private void emit_sof(JPEG_MARKER code)
        {
            emit_marker(code);

            emit_2bytes(3 * m_cinfo.m_num_components + 2 + 5 + 1); /* length */

            /* Make sure image isn't bigger than SOF field can handle */
            if (m_cinfo.m_image_height > 65535 || m_cinfo.m_image_width > 65535)
            {
                m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_IMAGE_TOO_BIG, 65535);
            }

            emit_byte(m_cinfo.m_data_precision);
            emit_2bytes(m_cinfo.m_image_height);
            emit_2bytes(m_cinfo.m_image_width);

            emit_byte(m_cinfo.m_num_components);

            for (int ci = 0; ci < m_cinfo.m_num_components; ci++)
            {
                jpeg_component_info componentInfo = m_cinfo.Component_info[ci];
                emit_byte(componentInfo.Component_id);
                emit_byte((componentInfo.H_samp_factor << 4) + componentInfo.V_samp_factor);
                emit_byte(componentInfo.Quant_tbl_no);
            }
        }
Example #7
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;
            }
        }
Example #8
0
        // Process some data in subsequent passes of a multi-pass case.
        // We process the equivalent of one fully interleaved MCU row ("iMCU" row)
        // per call, ie, v_samp_factor block rows for each component in the scan.
        // The data is obtained from the arrays and fed to the entropy coder.
        // Returns true if the iMCU row is completed, false if suspended.
        //
        // NB: input_buf is ignored; it is likely to be a null pointer.
        static bool compress_output_coef(jpeg_compress cinfo, byte[][][] input_buf)
        {
            jpeg_lossy_c_codec lossyc = (jpeg_lossy_c_codec)cinfo.coef;
            c_coef_controller  coef   = (c_coef_controller)lossyc.coef_private;

            short[][][][] buffer     = new short[MAX_COMPS_IN_SCAN][][][];
            int[]         buffer_ind = new int[MAX_COMPS_IN_SCAN];

            // Align the buffers for the components used in this scan.
            // NB: during first pass, this is safe only because the buffers will
            // already be aligned properly, so jmemmgr.cs won't need to do any I/O.
            for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
            {
                jpeg_component_info compptr = cinfo.cur_comp_info[ci];
                buffer[ci]     = coef.whole_image[compptr.component_index];
                buffer_ind[ci] = (int)coef.iMCU_row_num * compptr.v_samp_factor;
            }

            // Loop to process one whole iMCU row
            for (int yoffset = coef.MCU_vert_offset; yoffset < coef.MCU_rows_per_iMCU_row; yoffset++)
            {
                for (uint MCU_col_num = coef.mcu_ctr; MCU_col_num < cinfo.MCUs_per_row; MCU_col_num++)
                {
                    // Construct list of pointers to DCT blocks belonging to this MCU
                    int blkn = 0;                   // index of current DCT block within MCU
                    for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
                    {
                        jpeg_component_info compptr = cinfo.cur_comp_info[ci];
                        uint start_col = MCU_col_num * (uint)compptr.MCU_width;
                        for (int yindex = 0; yindex < compptr.MCU_height; yindex++)
                        {
                            short[][] buffer_ptr     = buffer[ci][buffer_ind[ci] + yindex + yoffset];
                            uint      buffer_ptr_ind = start_col;
                            for (int xindex = 0; xindex < compptr.MCU_width; xindex++)
                            {
                                coef.MCU_buffer[blkn++] = buffer_ptr[buffer_ptr_ind++];
                            }
                        }
                    }

                    // Try to write the MCU.
                    if (!lossyc.entropy_encode_mcu(cinfo, coef.MCU_buffer))
                    {
                        // Suspension forced; update state counters and exit
                        coef.MCU_vert_offset = yoffset;
                        coef.mcu_ctr         = MCU_col_num;
                        return(false);
                    }
                }

                // Completed an MCU row, but perhaps not an iMCU row
                coef.mcu_ctr = 0;
            }

            // Completed the iMCU row, advance counters for next one
            coef.iMCU_row_num++;
            start_iMCU_row_c_coef(cinfo);

            return(true);
        }
Example #9
0
        // Trial-encode one MCU's worth of Huffman-compressed coefficients.
        // No data is actually output, so no suspension return is possible.
        static bool encode_mcu_gather_sq(jpeg_compress cinfo, short[][] MCU_data)
        {
            jpeg_lossy_c_codec    lossyc  = (jpeg_lossy_c_codec)cinfo.coef;
            shuff_entropy_encoder entropy = (shuff_entropy_encoder)lossyc.entropy_private;

            // Take care of restart intervals if needed
            if (cinfo.restart_interval != 0)
            {
                if (entropy.restarts_to_go == 0)
                {
                    // Re-initialize DC predictions to 0
                    for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
                    {
                        entropy.saved.last_dc_val[ci] = 0;
                    }
                    // Update restart state
                    entropy.restarts_to_go = cinfo.restart_interval;
                }
                entropy.restarts_to_go--;
            }

            for (int blkn = 0; blkn < cinfo.block_in_MCU; blkn++)
            {
                int ci = cinfo.MCU_membership[blkn];
                jpeg_component_info compptr = cinfo.cur_comp_info[ci];
                htest_one_block_sq(cinfo, MCU_data[blkn], entropy.saved.last_dc_val[ci], entropy.dc_count_ptrs[compptr.dc_tbl_no], entropy.ac_count_ptrs[compptr.ac_tbl_no]);
                entropy.saved.last_dc_val[ci] = MCU_data[blkn][0];
            }

            return(true);
        }
Example #10
0
		// Emit a SOS marker
		static void emit_sos(jpeg_compress cinfo)
		{
			emit_marker(cinfo, JPEG_MARKER.M_SOS);

			emit_2bytes(cinfo, 2*cinfo.comps_in_scan+2+1+3); // length

			emit_byte(cinfo, cinfo.comps_in_scan);

			for(int i=0; i<cinfo.comps_in_scan; i++)
			{
				jpeg_component_info compptr=cinfo.cur_comp_info[i];
				emit_byte(cinfo, compptr.component_id);
				int td=compptr.dc_tbl_no;
				int ta=compptr.ac_tbl_no;
				if(cinfo.process==J_CODEC_PROCESS.JPROC_PROGRESSIVE)
				{
					// Progressive mode: only DC or only AC tables are used in one scan;
					// furthermore, Huffman coding of DC refinement uses no table at all.
					// We emit 0 for unused field(s); this is recommended by the P&M text
					// but does not seem to be specified in the standard.
					if(cinfo.Ss==0)
					{
						ta=0; // DC scan
						if(cinfo.Ah!=0&&!cinfo.arith_code) td=0; // no DC table either
					}
					else td=0; // AC scan
				}
				emit_byte(cinfo, (td<<4)+ta);
			}

			emit_byte(cinfo, cinfo.Ss);
			emit_byte(cinfo, cinfo.Se);
			emit_byte(cinfo, (cinfo.Ah<<4)+cinfo.Al);
		}
Example #11
0
        /// <summary>
        /// Process some data in subsequent passes of a multi-pass case.
        /// We process the equivalent of one fully interleaved MCU row ("iMCU" row)
        /// per call, ie, v_samp_factor block rows for each component in the scan.
        /// The data is obtained from the virtual arrays and fed to the entropy coder.
        /// Returns true if the iMCU row is completed, false if suspended.
        /// </summary>
        private bool compressOutput()
        {
            /* Align the virtual buffers for the components used in this scan.
             */
            JBLOCK[][][] buffer = new JBLOCK[JpegConstants.MAX_COMPS_IN_SCAN][][];
            for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
            {
                jpeg_component_info componentInfo = m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]];
                buffer[ci] = m_whole_image[componentInfo.Component_index].Access(
                    m_iMCU_row_num * componentInfo.V_samp_factor, componentInfo.V_samp_factor);
            }

            /* Loop to process one whole iMCU row */
            for (int yoffset = m_MCU_vert_offset; yoffset < m_MCU_rows_per_iMCU_row; yoffset++)
            {
                for (int MCU_col_num = m_mcu_ctr; MCU_col_num < m_cinfo.m_MCUs_per_row; MCU_col_num++)
                {
                    /* Construct list of pointers to DCT blocks belonging to this MCU */
                    int blkn = 0;           /* index of current DCT block within MCU */
                    for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
                    {
                        jpeg_component_info componentInfo = m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]];
                        int start_col = MCU_col_num * componentInfo.MCU_width;
                        for (int yindex = 0; yindex < componentInfo.MCU_height; yindex++)
                        {
                            for (int xindex = 0; xindex < componentInfo.MCU_width; xindex++)
                            {
                                int bufLength = buffer[ci][yindex + yoffset].Length;
                                int start     = start_col + xindex;
                                m_MCU_buffer[blkn] = new JBLOCK[bufLength - start];
                                for (int j = start; j < bufLength; j++)
                                {
                                    m_MCU_buffer[blkn][j - start] = buffer[ci][yindex + yoffset][j];
                                }

                                blkn++;
                            }
                        }
                    }

                    /* Try to write the MCU. */
                    if (!m_cinfo.m_entropy.encode_mcu(m_MCU_buffer))
                    {
                        /* Suspension forced; update state counters and exit */
                        m_MCU_vert_offset = yoffset;
                        m_mcu_ctr         = MCU_col_num;
                        return(false);
                    }
                }

                /* Completed an MCU row, but perhaps not an iMCU row */
                m_mcu_ctr = 0;
            }

            /* Completed the iMCU row, advance counters for next one */
            m_iMCU_row_num++;
            start_iMCU_row();
            return(true);
        }
Example #12
0
        // Initialize for a Huffman-compressed scan.
        static void start_pass_huff_decoder(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec    lossyd  = (jpeg_lossy_d_codec)cinfo.coef;
            shuff_entropy_decoder entropy = (shuff_entropy_decoder)lossyd.entropy_private;

            // Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG.
            // This ought to be an error condition, but we make it a warning because
            // there are some baseline files out there with all zeroes in these bytes.
            if (cinfo.Ss != 0 || cinfo.Se != DCTSIZE2 - 1 || cinfo.Ah != 0 || cinfo.Al != 0)
            {
                WARNMS(cinfo, J_MESSAGE_CODE.JWRN_NOT_SEQUENTIAL);
            }

            for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
            {
                jpeg_component_info compptr = cinfo.cur_comp_info[ci];
                int dctbl = compptr.dc_tbl_no;
                int actbl = compptr.ac_tbl_no;

                // Compute derived values for Huffman tables
                // We may do this more than once for a table, but it's not expensive
                jpeg_make_d_derived_tbl(cinfo, true, dctbl, ref entropy.dc_derived_tbls[dctbl]);
                jpeg_make_d_derived_tbl(cinfo, false, actbl, ref entropy.ac_derived_tbls[actbl]);

                // Initialize DC predictions to 0
                entropy.saved.last_dc_val[ci] = 0;
            }

            // Precalculate decoding info for each block in an MCU of this scan
            for (int blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++)
            {
                int ci = cinfo.MCU_membership[blkn];
                jpeg_component_info compptr = cinfo.cur_comp_info[ci];

                // Precalculate which table to use for each block
                entropy.dc_cur_tbls[blkn] = entropy.dc_derived_tbls[compptr.dc_tbl_no];
                entropy.ac_cur_tbls[blkn] = entropy.ac_derived_tbls[compptr.ac_tbl_no];

                // Decide whether we really care about the coefficient values
                if (compptr.component_needed)
                {
                    entropy.dc_needed[blkn] = true;
                    // we don't need the ACs if producing a 1/8th-size image
                    entropy.ac_needed[blkn] = (compptr.DCT_scaled_size > 1);
                }
                else
                {
                    entropy.dc_needed[blkn] = entropy.ac_needed[blkn] = false;
                }
            }

            // Initialize bitread state variables
            entropy.bitstate.bits_left  = 0;
            entropy.bitstate.get_buffer = 0;           // unnecessary, but keeps Purify quiet
            entropy.insufficient_data   = false;

            // Initialize restart counter
            entropy.restarts_to_go = cinfo.restart_interval;
        }
        /// <summary>
        /// Initialize for a Huffman-compressed scan.
        /// </summary>
        public override void start_pass()
        {
            /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG.
             * This ought to be an error condition, but we make it a warning because
             * there are some baseline files out there with all zeroes in these bytes.
             */
            if (m_cinfo.m_Ss != 0 || m_cinfo.m_Se != JpegConstants.DCTSIZE2 - 1 || m_cinfo.m_Ah != 0 || m_cinfo.m_Al != 0)
            {
                m_cinfo.WARNMS(J_MESSAGE_CODE.JWRN_NOT_SEQUENTIAL);
            }

            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]];
                int dctbl = componentInfo.Dc_tbl_no;
                int actbl = componentInfo.Ac_tbl_no;

                /* Compute derived values for Huffman tables */
                /* We may do this more than once for a table, but it's not expensive */
                jpeg_make_d_derived_tbl(true, dctbl, ref m_dc_derived_tbls[dctbl]);
                jpeg_make_d_derived_tbl(false, actbl, ref m_ac_derived_tbls[actbl]);

                /* Initialize DC predictions to 0 */
                m_saved.last_dc_val[ci] = 0;
            }

            /* Precalculate decoding info for each block in an MCU of this scan */
            for (int blkn = 0; blkn < m_cinfo.m_blocks_in_MCU; blkn++)
            {
                int ci = m_cinfo.m_MCU_membership[blkn];
                jpeg_component_info componentInfo = m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[ci]];

                /* Precalculate which table to use for each block */
                m_dc_cur_tbls[blkn] = m_dc_derived_tbls[componentInfo.Dc_tbl_no];
                m_ac_cur_tbls[blkn] = m_ac_derived_tbls[componentInfo.Ac_tbl_no];

                /* Decide whether we really care about the coefficient values */
                if (componentInfo.component_needed)
                {
                    m_dc_needed[blkn] = true;
                    /* we don't need the ACs if producing a 1/8th-size image */
                    m_ac_needed[blkn] = (componentInfo.DCT_scaled_size > 1);
                }
                else
                {
                    m_dc_needed[blkn] = m_ac_needed[blkn] = false;
                }
            }

            /* Initialize bitread state variables */
            m_bitstate.bits_left  = 0;
            m_bitstate.get_buffer = 0;
            m_insufficient_data   = false;

            /* Initialize restart counter */
            m_restarts_to_go = m_cinfo.m_restart_interval;
        }
        /// <summary>
        /// Downsample pixel values of a single component.
        /// This version handles the special case of a full-size component,
        /// without smoothing.
        /// </summary>
        private void fullsize_downsample(int componentIndex, byte[][] input_data, int startInputRow, byte[][] output_data, int startOutRow)
        {
            /* Copy the data */
            JpegUtils.jcopy_sample_rows(input_data, startInputRow, output_data, startOutRow, m_cinfo.m_max_v_samp_factor, m_cinfo.m_image_width);

            /* Edge-expand */
            jpeg_component_info compptr = m_cinfo.Component_info[componentIndex];

            expand_right_edge(output_data, startOutRow, m_cinfo.m_max_v_samp_factor,
                              m_cinfo.m_image_width, compptr.Width_in_blocks * compptr.DCT_h_scaled_size);
        }
Example #15
0
		// Write scan header.
		// This consists of DHT or DAC markers, optional DRI, and SOS.
		// Compressed data will be written following the SOS.
		static void write_scan_header(jpeg_compress cinfo)
		{
			if(cinfo.arith_code)
			{
				// Emit arith conditioning info. We may have some duplication
				// if the file has multiple scans, but it's so small it's hardly
				// worth worrying about.
				emit_dac(cinfo);
			}
			else
			{
				// Emit Huffman tables.
				// Note that emit_dht() suppresses any duplicate tables.
				for(int i=0; i<cinfo.comps_in_scan; i++)
				{
					jpeg_component_info compptr=cinfo.cur_comp_info[i];
					if(cinfo.process==J_CODEC_PROCESS.JPROC_PROGRESSIVE)
					{
						// Progressive mode: only DC or only AC tables are used in one scan
						if(cinfo.Ss==0)
						{
							if(cinfo.Ah==0) emit_dht(cinfo, compptr.dc_tbl_no, false); // DC needs no table for refinement scan
						}
						else
						{
							emit_dht(cinfo, compptr.ac_tbl_no, true);
						}
					}
					else if(cinfo.process==J_CODEC_PROCESS.JPROC_LOSSLESS)
					{
						// Lossless mode: only DC tables are used
						emit_dht(cinfo, compptr.dc_tbl_no, false);
					}
					else
					{
						// Sequential mode: need both DC and AC tables
						emit_dht(cinfo, compptr.dc_tbl_no, false);
						emit_dht(cinfo, compptr.ac_tbl_no, true);
					}
				}
			}

			my_marker_writer marker=(my_marker_writer)cinfo.marker;

			// Emit DRI if required --- note that DRI value could change for each scan.
			// We avoid wasting space with unnecessary DRIs, however.
			if(cinfo.restart_interval!=marker.last_restart_interval)
			{
				emit_dri(cinfo);
				marker.last_restart_interval=cinfo.restart_interval;
			}

			emit_sos(cinfo);
		}
Example #16
0
        /// <summary>
        /// Process some data in the simple no-context case.
        ///
        /// Preprocessor output data is counted in "row groups".  A row group
        /// is defined to be v_samp_factor sample rows of each component.
        /// Downsampling will produce this much data from each max_v_samp_factor
        /// input rows.
        /// </summary>
        private void pre_process_WithoutContext(byte[][] input_buf, ref int in_row_ctr, int in_rows_avail, byte[][][] output_buf, ref int out_row_group_ctr, int out_row_groups_avail)
        {
            while (in_row_ctr < in_rows_avail && out_row_group_ctr < out_row_groups_avail)
            {
                /* Do color conversion to fill the conversion buffer. */
                int inrows  = in_rows_avail - in_row_ctr;
                int numrows = m_cinfo.m_max_v_samp_factor - m_next_buf_row;
                numrows = Math.Min(numrows, inrows);
                m_cinfo.m_cconvert.color_convert(input_buf, in_row_ctr, m_color_buf, m_colorBufRowsOffset + m_next_buf_row, numrows);
                in_row_ctr     += numrows;
                m_next_buf_row += numrows;
                m_rows_to_go   -= numrows;

                /* If at bottom of image, pad to fill the conversion buffer. */
                if (m_rows_to_go == 0 && m_next_buf_row < m_cinfo.m_max_v_samp_factor)
                {
                    for (int ci = 0; ci < m_cinfo.m_num_components; ci++)
                    {
                        expand_bottom_edge(m_color_buf[ci], m_colorBufRowsOffset, m_cinfo.m_image_width, m_next_buf_row, m_cinfo.m_max_v_samp_factor);
                    }

                    m_next_buf_row = m_cinfo.m_max_v_samp_factor;
                }

                /* If we've filled the conversion buffer, empty it. */
                if (m_next_buf_row == m_cinfo.m_max_v_samp_factor)
                {
                    m_cinfo.m_downsample.downsample(m_color_buf, m_colorBufRowsOffset, output_buf, out_row_group_ctr);
                    m_next_buf_row = 0;
                    out_row_group_ctr++;
                }

                /* If at bottom of image, pad the output to a full iMCU height.
                 * Note we assume the caller is providing a one-iMCU-height output buffer!
                 */
                if (m_rows_to_go == 0 && out_row_group_ctr < out_row_groups_avail)
                {
                    for (int ci = 0; ci < m_cinfo.m_num_components; ci++)
                    {
                        jpeg_component_info componentInfo = m_cinfo.Component_info[ci];
                        numrows = (componentInfo.V_samp_factor * componentInfo.DCT_v_scaled_size) /
                                  m_cinfo.min_DCT_v_scaled_size;

                        expand_bottom_edge(output_buf[ci], 0,
                                           componentInfo.Width_in_blocks * componentInfo.DCT_h_scaled_size,
                                           out_row_group_ctr * numrows,
                                           out_row_groups_avail * numrows);
                    }

                    out_row_group_ctr = out_row_groups_avail;
                    break;          /* can exit outer loop without test */
                }
            }
        }
        /// <summary>
        /// Finish up a statistics-gathering pass and create the new Huffman tables.
        /// </summary>
        private void finish_pass_gather_phuff()
        {
            /* Flush out buffered data (all we care about is counting the EOB symbol) */
            emit_eobrun();

            /* It's important not to apply jpeg_gen_optimal_table more than once
             * per table, because it clobbers the input frequency counts!
             */
            bool[] did = new bool [JpegConstants.NUM_HUFF_TBLS];

            bool is_DC_band = (m_cinfo.m_Ss == 0);

            for (int ci = 0; ci < m_cinfo.m_comps_in_scan; ci++)
            {
                jpeg_component_info componentInfo = m_cinfo.Component_info[m_cinfo.m_cur_comp_info[ci]];
                int tbl = componentInfo.Ac_tbl_no;

                if (is_DC_band)
                {
                    if (m_cinfo.m_Ah != 0) /* DC refinement needs no table */
                    {
                        continue;
                    }

                    tbl = componentInfo.Dc_tbl_no;
                }

                if (!did[tbl])
                {
                    JHUFF_TBL htblptr = null;
                    if (is_DC_band)
                    {
                        if (m_cinfo.m_dc_huff_tbl_ptrs[tbl] == null)
                        {
                            m_cinfo.m_dc_huff_tbl_ptrs[tbl] = new JHUFF_TBL();
                        }

                        htblptr = m_cinfo.m_dc_huff_tbl_ptrs[tbl];
                    }
                    else
                    {
                        if (m_cinfo.m_ac_huff_tbl_ptrs[tbl] == null)
                        {
                            m_cinfo.m_ac_huff_tbl_ptrs[tbl] = new JHUFF_TBL();
                        }

                        htblptr = m_cinfo.m_ac_huff_tbl_ptrs[tbl];
                    }

                    jpeg_gen_optimal_table(htblptr, m_count_ptrs[tbl]);
                    did[tbl] = true;
                }
            }
        }
Example #18
0
        // Finish up a statistics-gathering pass and create the new Huffman tables.
        static void finish_pass_gather_phuff(jpeg_compress cinfo)
        {
            jpeg_lossy_c_codec    lossyc  = (jpeg_lossy_c_codec)cinfo.coef;
            phuff_entropy_encoder entropy = (phuff_entropy_encoder)lossyc.entropy_private;

            // Flush out buffered data (all we care about is counting the EOB symbol)
            emit_eobrun(entropy);

            bool is_DC_band = (cinfo.Ss == 0);

            // It's important not to apply jpeg_gen_optimal_table more than once
            // per table, because it clobbers the input frequency counts!
            bool[] did = new bool[NUM_HUFF_TBLS];

            for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
            {
                jpeg_component_info compptr = cinfo.cur_comp_info[ci];
                int tbl;
                if (is_DC_band)
                {
                    if (cinfo.Ah != 0)
                    {
                        continue;                                 // DC refinement needs no table
                    }
                    tbl = compptr.dc_tbl_no;
                }
                else
                {
                    tbl = compptr.ac_tbl_no;
                }

                if (!did[tbl])
                {
                    if (is_DC_band)
                    {
                        if (cinfo.dc_huff_tbl_ptrs[tbl] == null)
                        {
                            cinfo.dc_huff_tbl_ptrs[tbl] = jpeg_alloc_huff_table(cinfo);
                        }
                        jpeg_gen_optimal_table(cinfo, cinfo.dc_huff_tbl_ptrs[tbl], entropy.count_ptrs[tbl]);
                    }
                    else
                    {
                        if (cinfo.ac_huff_tbl_ptrs[tbl] == null)
                        {
                            cinfo.ac_huff_tbl_ptrs[tbl] = jpeg_alloc_huff_table(cinfo);
                        }
                        jpeg_gen_optimal_table(cinfo, cinfo.ac_huff_tbl_ptrs[tbl], entropy.count_ptrs[tbl]);
                    }
                    did[tbl] = true;
                }
            }
        }
Example #19
0
        // Initialize coefficient buffer controller.
        static void jinit_d_coef_controller(jpeg_decompress cinfo, bool need_full_buffer)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;
            d_coef_controller  coef   = null;

            try
            {
                coef = new d_coef_controller();
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }
            lossyd.coef_private           = coef;
            lossyd.coef_start_input_pass  = start_input_pass_d_coef;
            lossyd.coef_start_output_pass = start_output_pass_d_coef;
#if BLOCK_SMOOTHING_SUPPORTED
            coef.coef_bits_latch = null;
#endif

            // Create the coefficient buffer.
            if (need_full_buffer)
            {
#if D_MULTISCAN_FILES_SUPPORTED
                // Allocate a full-image array for each component,
                // padded to a multiple of samp_factor DCT blocks in each direction.
                // Note we ask for a pre-zeroed array.
                for (int ci = 0; ci < cinfo.num_components; ci++)
                {
                    jpeg_component_info compptr = cinfo.comp_info[ci];
                    int access_rows             = compptr.v_samp_factor;
                    coef.whole_image[ci] = alloc_barray(cinfo, (uint)jround_up(compptr.width_in_blocks, compptr.h_samp_factor), (uint)jround_up(compptr.height_in_blocks, compptr.v_samp_factor));
                }
                lossyd.consume_data    = consume_data;
                lossyd.decompress_data = decompress_data;
                lossyd.coef_arrays     = coef.whole_image;           // link to arrays
#else
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED);
#endif
            }
            else
            {
                // We only need a single-MCU buffer.
                for (int i = 0; i < D_MAX_BLOCKS_IN_MCU; i++)
                {
                    coef.MCU_buffer[i] = new short[DCTSIZE2];
                }

                lossyd.consume_data    = dummy_consume_data_d_coef;
                lossyd.decompress_data = decompress_onepass;
                lossyd.coef_arrays     = null;           // flag for no arrays
            }
        }
Example #20
0
        static void jinit_c_coef_controller(jpeg_compress cinfo, bool need_full_buffer)
        {
            jpeg_lossy_c_codec lossyc = (jpeg_lossy_c_codec)cinfo.coef;
            c_coef_controller  coef   = null;

            try
            {
                coef = new c_coef_controller();
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }

            lossyc.coef_private    = coef;
            lossyc.coef_start_pass = start_pass_coef;

            // Create the coefficient buffer.
            if (need_full_buffer)
            {
#if FULL_COEF_BUFFER_SUPPORTED
                // Allocate a full-image array for each component,
                // padded to a multiple of samp_factor DCT blocks in each direction.
                for (int ci = 0; ci < cinfo.num_components; ci++)
                {
                    jpeg_component_info compptr = cinfo.comp_info[ci];

                    coef.whole_image[ci] = alloc_barray(cinfo,
                                                        (uint)jround_up((int)compptr.width_in_blocks, compptr.h_samp_factor),
                                                        (uint)jround_up((int)compptr.height_in_blocks, compptr.v_samp_factor));
                }
#else
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
#endif
            }
            else
            {
                // We only need a single-MCU buffer.
                try
                {
                    for (int i = 0; i < C_MAX_BLOCKS_IN_MCU; i++)
                    {
                        coef.MCU_buffer[i] = new short[DCTSIZE2];
                    }
                }
                catch
                {
                    ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
                }

                coef.whole_image[0] = null;               // flag for no arrays
            }
        }
Example #21
0
        // This version is used for floating-point DCT implementations.
        static void forward_DCT_float(jpeg_compress cinfo, jpeg_component_info compptr, byte[][] sample_data, short[][] coef_blocks, int coef_offset, uint start_row, uint start_col, uint num_blocks)
        {
            // This routine is heavily used, so it's worth coding it tightly
            jpeg_lossy_c_codec lossyc = (jpeg_lossy_c_codec)cinfo.coef;
            fdct_controller    fdct   = (fdct_controller)lossyc.fdct_private;

            float_DCT_method_ptr do_dct = fdct.do_float_dct;

            double[] divisors  = fdct.float_divisors[compptr.quant_tbl_no];
            double[] workspace = new double[DCTSIZE2];                  // work area for FDCT subroutine

            for (int bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE)
            {
                // Load data into workspace, applying unsigned->signed conversion
                int wsptr = 0;
                for (int elemr = 0; elemr < DCTSIZE; elemr++)
                {
                    byte[] elem = sample_data[start_row + elemr];
                    uint   eptr = start_col;

                    // unroll the inner loop
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                    workspace[wsptr++] = elem[eptr++] - CENTERJSAMPLE;
                }

                // Perform the DCT
                do_dct(workspace);

                // Quantize/descale the coefficients, and store into coef_blocks[]
                //old short[] output_ptr=coef_blocks[coef_offset][bi];
                short[] output_ptr = coef_blocks[coef_offset + bi];

                for (int i = 0; i < DCTSIZE2; i++)
                {
                    // Apply the quantization and scaling factor
                    double temp = workspace[i] * divisors[i];

                    // Round to nearest integer.
                    // Since C does not specify the direction of rounding for negative
                    // quotients, we have to force the dividend positive for portability.
                    // The maximum coefficient size is +-16K (for 12-bit data), so this
                    // code should work for either 16-bit or 32-bit ints.
                    output_ptr[i] = (short)((int)(temp + 16384.5) - 16384);
                }
            }
        }
Example #22
0
        public jpeg_c_main_controller(jpeg_compress_struct cinfo)
        {
            m_cinfo = cinfo;

            /* Allocate a strip buffer for each component */
            for (int ci = 0; ci < cinfo.m_num_components; ci++)
            {
                jpeg_component_info compptr = cinfo.Component_info[ci];
                m_buffer[ci] = jpeg_common_struct.AllocJpegSamples(
                    compptr.Width_in_blocks * compptr.DCT_h_scaled_size,
                    compptr.V_samp_factor * compptr.DCT_v_scaled_size);
            }
        }
Example #23
0
        /* Emit a DAC marker */
        /* Since the useful info is so small, we want to emit all the tables in */
        /* one DAC marker.  Therefore this routine does its own scan of the table. */
        private void emit_dac()
        {
            byte[] dc_in_use = new byte[JpegConstants.NUM_ARITH_TBLS];
            byte[] ac_in_use = new byte[JpegConstants.NUM_ARITH_TBLS];

            for (int i = 0; i < m_cinfo.m_comps_in_scan; i++)
            {
                jpeg_component_info compptr = m_cinfo.Component_info[m_cinfo.m_cur_comp_info[i]];
                /* DC needs no table for refinement scan */
                if (m_cinfo.m_Ss == 0 && m_cinfo.m_Ah == 0)
                {
                    dc_in_use[compptr.Dc_tbl_no] = 1;
                }

                /* AC needs no table when not present */
                if (m_cinfo.m_Se != 0)
                {
                    ac_in_use[compptr.Ac_tbl_no] = 1;
                }
            }

            int length = 0;

            for (int i = 0; i < JpegConstants.NUM_ARITH_TBLS; i++)
            {
                length += dc_in_use[i] + ac_in_use[i];
            }

            if (length != 0)
            {
                emit_marker(JPEG_MARKER.DAC);

                emit_2bytes(length * 2 + 2);

                for (int i = 0; i < JpegConstants.NUM_ARITH_TBLS; i++)
                {
                    if (dc_in_use[i] != 0)
                    {
                        emit_byte(i);
                        emit_byte(m_cinfo.arith_dc_L[i] + (m_cinfo.arith_dc_U[i] << 4));
                    }
                    if (ac_in_use[i] != 0)
                    {
                        emit_byte(i + 0x10);
                        emit_byte(m_cinfo.arith_ac_K[i]);
                    }
                }
            }
        }
Example #24
0
        /// <summary>
        /// Write scan header.
        /// This consists of DHT or DAC markers, optional DRI, and SOS.
        /// Compressed data will be written following the SOS.
        /// </summary>
        public void write_scan_header()
        {
            if (m_cinfo.arith_code)
            {
                /* Emit arith conditioning info.  We may have some duplication
                 * if the file has multiple scans, but it's so small it's hardly
                 * worth worrying about.
                 */
                emit_dac();
            }
            else
            {
                /* Emit Huffman tables.
                 * Note that emit_dht() suppresses any duplicate tables.
                 */
                for (int i = 0; i < m_cinfo.m_comps_in_scan; i++)
                {
                    jpeg_component_info compptr = m_cinfo.Component_info[m_cinfo.m_cur_comp_info[i]];

                    /* DC needs no table for refinement scan */
                    if (m_cinfo.m_Ss == 0 && m_cinfo.m_Ah == 0)
                    {
                        emit_dht(compptr.Dc_tbl_no, false);
                    }

                    /* AC needs no table when not present */
                    if (m_cinfo.m_Se != 0)
                    {
                        emit_dht(compptr.Ac_tbl_no, true);
                    }
                }

                /* Emit DRI if required --- note that DRI value could change for each scan.
                 * We avoid wasting space with unnecessary DRIs, however.
                 */
                if (m_cinfo.m_restart_interval != m_last_restart_interval)
                {
                    emit_dri();
                    m_last_restart_interval = m_cinfo.m_restart_interval;
                }

                emit_sos();
            }
        }
Example #25
0
        // Initialize main buffer controller.
        public static void jinit_d_main_controller(jpeg_decompress cinfo, bool need_full_buffer)
        {
            my_d_main_controller main = null;

            try
            {
                main = new my_d_main_controller();
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }

            cinfo.main      = main;
            main.start_pass = start_pass_d_main;

            if (need_full_buffer)
            {
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);                              // shouldn't happen
            }
            // Allocate the workspace.
            // ngroups is the number of row groups we need.
            int ngroups = cinfo.min_DCT_scaled_size;

#if UPSCALING_CONTEXT
            if (cinfo.upsample.need_context_rows)
            {
                if (cinfo.min_DCT_scaled_size < 2)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOTIMPL);                                             // unsupported, see comments above
                }
                ngroups = cinfo.min_DCT_scaled_size + 2;
            }
#endif

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

                int rgroup = (compptr.v_samp_factor * (int)compptr.DCT_scaled_size) / cinfo.min_DCT_scaled_size;           // height of a row group of component
                main.buffer[ci] = alloc_sarray(cinfo, compptr.width_in_blocks * compptr.DCT_scaled_size, (uint)(rgroup * ngroups));
            }
        }
Example #26
0
        // Emit a restart marker & resynchronize predictions.
        static void emit_restart_arith(jpeg_compress cinfo, int restart_num)
        {
            arith_entropy_encoder entropy = (arith_entropy_encoder)cinfo.coef;

            finish_pass_c_arith(cinfo);

            emit_byte(cinfo, 0xFF);
            emit_byte(cinfo, JPEG_RST0 + restart_num);

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

                // Re-initialize statistics areas
                if (cinfo.process != J_CODEC_PROCESS.JPROC_PROGRESSIVE || (cinfo.Ss == 0 && cinfo.Ah == 0))
                {
                    for (int i = 0; i < DC_STAT_BINS; i++)
                    {
                        entropy.dc_stats[compptr.dc_tbl_no][i] = 0;
                    }
                    // Reset DC predictions to 0
                    entropy.last_dc_val[ci] = 0;
                    entropy.dc_context[ci]  = 0;
                }

                if (cinfo.process != J_CODEC_PROCESS.JPROC_PROGRESSIVE || cinfo.Ss != 0)
                {
                    for (int i = 0; i < AC_STAT_BINS; i++)
                    {
                        entropy.ac_stats[compptr.ac_tbl_no][i] = 0;
                    }
                }
            }

            // Reset arithmetic encoding variables
            entropy.c      = 0;
            entropy.a      = 0x10000;
            entropy.sc     = 0;
            entropy.zc     = 0;
            entropy.ct     = 11;
            entropy.buffer = -1;                // empty
        }
Example #27
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;
                }
            }
        }
Example #28
0
        // Check for a restart marker & resynchronize decoder.
        static void process_restart_arith(jpeg_decompress cinfo)
        {
            arith_entropy_decoder entropy = (arith_entropy_decoder)cinfo.coef;

            // Advance past the RSTn marker
            if (!cinfo.marker.read_restart_marker(cinfo))
            {
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CANT_SUSPEND);
            }

            for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
            {
                jpeg_component_info compptr = cinfo.cur_comp_info[ci];
                // Re-initialize statistics areas
                if (cinfo.process == J_CODEC_PROCESS.JPROC_SEQUENTIAL || (cinfo.Ss == 0 && cinfo.Ah == 0))
                {
                    for (int i = 0; i < DC_STAT_BINS; i++)
                    {
                        entropy.dc_stats[compptr.dc_tbl_no][i] = 0;
                    }

                    // Reset DC predictions to 0
                    entropy.last_dc_val[ci] = 0;
                    entropy.dc_context[ci]  = 0;
                }
                if (cinfo.process == J_CODEC_PROCESS.JPROC_SEQUENTIAL || cinfo.Ss != 0)
                {
                    for (int i = 0; i < AC_STAT_BINS; i++)
                    {
                        entropy.ac_stats[compptr.ac_tbl_no][i] = 0;
                    }
                }
            }

            // Reset arithmetic decoding variables
            entropy.c  = 0;
            entropy.a  = 0;
            entropy.ct = -16;           // force reading 2 initial bytes to fill C

            // Reset restart counter
            entropy.restarts_to_go = cinfo.restart_interval;
        }
Example #29
0
        // Initialize main buffer controller.
        static void jinit_c_main_controller(jpeg_compress cinfo, bool need_full_buffer)
        {
            my_c_main_controller main = null;

            try
            {
                main = new my_c_main_controller();
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }
            cinfo.main      = main;
            main.start_pass = start_pass_c_main;

            // We don't need to create a buffer in raw-data mode.
            if (cinfo.raw_data_in)
            {
                return;
            }

            // Create the buffer. It holds downsampled data, so each component
            // may be of a different size.
            if (need_full_buffer)
            {
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
            }
            else
            {
                uint DCT_size = cinfo.DCT_size;

                // Allocate a strip buffer for each component
                for (int ci = 0; ci < cinfo.num_components; ci++)
                {
                    jpeg_component_info compptr = cinfo.comp_info[ci];
                    main.buffer[ci] = alloc_sarray(cinfo, compptr.width_in_blocks * DCT_size, (uint)(compptr.v_samp_factor * DCT_size));
                }
            }
        }
        /// <summary>
        /// Downsample pixel values of a single component.
        /// One row group is processed per call.
        /// This version handles arbitrary integral sampling ratios, without smoothing.
        /// Note that this version is not actually used for customary sampling ratios.
        /// </summary>
        private void int_downsample(int componentIndex, byte[][] input_data, int startInputRow, byte[][] output_data, int startOutRow)
        {
            /* Expand input data enough to let all the output samples be generated
             * by the standard loop.  Special-casing padded output would be more
             * efficient.
             */
            jpeg_component_info compptr = m_cinfo.Component_info[componentIndex];
            int output_cols             = compptr.Width_in_blocks * compptr.DCT_h_scaled_size;
            int h_expand = this.h_expand[compptr.Component_index];

            expand_right_edge(input_data, startInputRow, m_cinfo.m_max_v_samp_factor, m_cinfo.m_image_width, output_cols * h_expand);

            int v_expand = this.v_expand[compptr.Component_index];
            int numpix   = h_expand * v_expand;
            int numpix2  = numpix / 2;
            int inrow    = 0;
            int outrow   = 0;

            while (inrow < m_cinfo.m_max_v_samp_factor)
            {
                for (int outcol = 0, outcol_h = 0; outcol < output_cols; outcol++, outcol_h += h_expand)
                {
                    int outvalue = 0;
                    for (int v = 0; v < v_expand; v++)
                    {
                        for (int h = 0; h < h_expand; h++)
                        {
                            outvalue += input_data[startInputRow + inrow + v][outcol_h + h];
                        }
                    }

                    output_data[startOutRow + outrow][outcol] = (byte)((outvalue + numpix2) / numpix);
                }

                inrow += v_expand;
                outrow++;
            }
        }
Example #31
0
		// Perform forward DCT on one or more blocks of a component.
		//
		// The input samples are taken from the sample_data[] array starting at
		// position start_row/start_col, and moving to the right for any additional
		// blocks. The quantized coefficients are returned in coef_blocks[].

		// This version is used for integer DCT implementations.
		static void forward_DCT(jpeg_compress cinfo, jpeg_component_info compptr, byte[][] sample_data, short[][] coef_blocks, int coef_offset, uint start_row, uint start_col, uint num_blocks)
		{
			// This routine is heavily used, so it's worth coding it tightly
			jpeg_lossy_c_codec lossyc=(jpeg_lossy_c_codec)cinfo.coef;
			fdct_controller fdct=(fdct_controller)lossyc.fdct_private;

			forward_DCT_method_ptr do_dct=fdct.do_dct;
			int[] divisors=fdct.divisors[compptr.quant_tbl_no];
			int[] workspace=new int[DCTSIZE2];	// work area for FDCT subroutine

			for(int bi=0; bi<num_blocks; bi++, start_col+=DCTSIZE)
			{
				// Load data into workspace, applying unsigned->signed conversion
				int wsptr=0;
				for(int elemr=0; elemr<DCTSIZE; elemr++)
				{
					byte[] elem=sample_data[start_row+elemr];
					uint eptr=start_col;

					// unroll the inner loop
					workspace[wsptr++]=elem[eptr++]-CENTERJSAMPLE;
					workspace[wsptr++]=elem[eptr++]-CENTERJSAMPLE;
					workspace[wsptr++]=elem[eptr++]-CENTERJSAMPLE;
					workspace[wsptr++]=elem[eptr++]-CENTERJSAMPLE;
					workspace[wsptr++]=elem[eptr++]-CENTERJSAMPLE;
					workspace[wsptr++]=elem[eptr++]-CENTERJSAMPLE;
					workspace[wsptr++]=elem[eptr++]-CENTERJSAMPLE;
					workspace[wsptr++]=elem[eptr++]-CENTERJSAMPLE;
				}

				// Perform the DCT
				do_dct(workspace);

				// Quantize/descale the coefficients, and store into coef_blocks[]
				//old short[] output_ptr=coef_blocks[coef_offset][bi];
				short[] output_ptr=coef_blocks[coef_offset+bi];

				for(int i=0; i<DCTSIZE2; i++)
				{
					int qval=divisors[i];
					int temp=workspace[i];
					// Divide the coefficient value by qval, ensuring proper rounding.
					// Since C does not specify the direction of rounding for negative
					// quotients, we have to force the dividend positive for portability.
					if(temp<0)
					{
						temp=-temp;
						temp+=qval>>1;	// for rounding
						temp/=qval;
						temp=-temp;
					}
					else
					{
						temp+=qval>>1;	// for rounding
						temp/=qval;
					}
					output_ptr[i]=(short)temp;
				}
			}
		}
Example #32
0
		// This version is used for floating-point DCT implementations.
		static void forward_DCT_float(jpeg_compress cinfo, jpeg_component_info compptr, byte[][] sample_data, short[][] coef_blocks, int coef_offset, uint start_row, uint start_col, uint num_blocks)
		{
			// This routine is heavily used, so it's worth coding it tightly
			jpeg_lossy_c_codec lossyc=(jpeg_lossy_c_codec)cinfo.coef;
			fdct_controller fdct=(fdct_controller)lossyc.fdct_private;

			float_DCT_method_ptr do_dct=fdct.do_float_dct;
			double[] divisors=fdct.float_divisors[compptr.quant_tbl_no];
			double[] workspace=new double[DCTSIZE2];	// work area for FDCT subroutine

			for(int bi=0; bi<num_blocks; bi++, start_col+=DCTSIZE)
			{
				// Load data into workspace, applying unsigned->signed conversion
				int wsptr=0;
				for(int elemr=0; elemr<DCTSIZE; elemr++)
				{
					byte[] elem=sample_data[start_row+elemr];
					uint eptr=start_col;

					// unroll the inner loop
					workspace[wsptr++]=elem[eptr++]-CENTERJSAMPLE;
					workspace[wsptr++]=elem[eptr++]-CENTERJSAMPLE;
					workspace[wsptr++]=elem[eptr++]-CENTERJSAMPLE;
					workspace[wsptr++]=elem[eptr++]-CENTERJSAMPLE;
					workspace[wsptr++]=elem[eptr++]-CENTERJSAMPLE;
					workspace[wsptr++]=elem[eptr++]-CENTERJSAMPLE;
					workspace[wsptr++]=elem[eptr++]-CENTERJSAMPLE;
					workspace[wsptr++]=elem[eptr++]-CENTERJSAMPLE;
				}

				// Perform the DCT
				do_dct(workspace);

				// Quantize/descale the coefficients, and store into coef_blocks[]
				//old short[] output_ptr=coef_blocks[coef_offset][bi];
				short[] output_ptr=coef_blocks[coef_offset+bi];

				for(int i=0; i<DCTSIZE2; i++)
				{
					// Apply the quantization and scaling factor
					double temp=workspace[i]*divisors[i];

					// Round to nearest integer.
					// Since C does not specify the direction of rounding for negative
					// quotients, we have to force the dividend positive for portability.
					// The maximum coefficient size is +-16K (for 12-bit data), so this
					// code should work for either 16-bit or 32-bit ints.
					output_ptr[i]=(short)((int)(temp+16384.5)-16384);
				}
			}
		}
Example #33
0
        // This version is used for floating-point DCT implementations.
        private void forwardDCTFloatImpl(jpeg_component_info compptr, byte[][] sample_data, JBLOCK[] coef_blocks, int start_row, int start_col, int num_blocks)
        {
            /* This routine is heavily used, so it's worth coding it tightly. */
            float_DCT_method_ptr do_dct = do_float_dct[compptr.Component_index];
            float[] divisors = m_dctTables[compptr.Component_index].float_array;
            float[] workspace = new float[JpegConstants.DCTSIZE2]; /* work area for FDCT subroutine */
            for (int bi = 0; bi < num_blocks; bi++, start_col += compptr.DCT_h_scaled_size)
            {
                /* Perform the DCT */
                do_dct(workspace, sample_data, start_row, start_col);

                /* Quantize/descale the coefficients, and store into coef_blocks[] */
                for (int i = 0; i < JpegConstants.DCTSIZE2; i++)
                {
                    /* Apply the quantization and scaling factor */
                    float temp = workspace[i] * divisors[i];

                    /* Round to nearest integer.
                     * Since C does not specify the direction of rounding for negative
                     * quotients, we have to force the dividend positive for portability.
                     * The maximum coefficient size is +-16K (for 12-bit data), so this
                     * code should work for either 16-bit or 32-bit ints.
                     */
                    coef_blocks[bi][i] = (short)((int)(temp + (float)16384.5) - 16384);
                }
            }
        }
Example #34
0
        // This version is used for integer DCT implementations.
        private void forwardDCTImpl(jpeg_component_info compptr, byte[][] sample_data, JBLOCK[] coef_blocks, int start_row, int start_col, int num_blocks)
        {
            /* This routine is heavily used, so it's worth coding it tightly. */
            forward_DCT_method_ptr do_dct = this.do_dct[compptr.Component_index];
            int[] divisors = m_dctTables[compptr.Component_index].int_array;
            int[] workspace = new int[JpegConstants.DCTSIZE2];    /* work area for FDCT subroutine */
            for (int bi = 0; bi < num_blocks; bi++, start_col += compptr.DCT_h_scaled_size)
            {
                /* Perform the DCT */
                do_dct(workspace, sample_data, start_row, start_col);

                /* Quantize/descale the coefficients, and store into coef_blocks[] */
                for (int i = 0; i < JpegConstants.DCTSIZE2; i++)
                {
                    int qval = divisors[i];
                    int temp = workspace[i];

                    if (temp < 0)
                    {
                        temp = -temp;
                        temp += qval >> 1;  /* for rounding */

                        if (temp >= qval)
                            temp /= qval;
                        else
                            temp = 0;

                        temp = -temp;
                    }
                    else
                    {
                        temp += qval >> 1;  /* for rounding */

                        if (temp >= qval)
                            temp /= qval;
                        else
                            temp = 0;
                    }

                    coef_blocks[bi][i] = (short)temp;
                }
            }
        }
Example #35
0
		// Perform dequantization and inverse DCT on one block of coefficients.
#if! USE_UNSAFE_STUFF
		static void jpeg_idct_ifast(jpeg_decompress cinfo, jpeg_component_info compptr, short[] coef_block, byte[][] output_buf, uint output_row, uint output_col)
		{
			int[] workspace=new int[DCTSIZE2];	// buffers data between passes

			// Pass 1: process columns from input, store into work array.
			short[] inptr=coef_block;
			int[] quantptr=compptr.dct_table;
			int[] wsptr=workspace;
			int ptr=0;
			for(int ctr=DCTSIZE; ctr>0; ctr--, ptr++) // ptr++: advance pointers to next column
			{
				// Due to quantization, we will usually find that many of the input
				// coefficients are zero, especially the AC terms. We can exploit this
				// by short-circuiting the IDCT calculation for any column in which all
				// the AC terms are zero. In that case each output is equal to the
				// DC coefficient (with scale factor as needed).
				// With typical images and quantization tables, half or more of the
				// column DCT calculations can be simplified this way.
				if(inptr[ptr+DCTSIZE*1]==0&&inptr[ptr+DCTSIZE*2]==0&&inptr[ptr+DCTSIZE*3]==0&&inptr[ptr+DCTSIZE*4]==0&&
					inptr[ptr+DCTSIZE*5]==0&&inptr[ptr+DCTSIZE*6]==0&&inptr[ptr+DCTSIZE*7]==0)
				{
					// AC terms all zero
					int dcval=inptr[ptr]*quantptr[ptr];

					wsptr[ptr]=dcval;
					wsptr[ptr+DCTSIZE*1]=dcval;
					wsptr[ptr+DCTSIZE*2]=dcval;
					wsptr[ptr+DCTSIZE*3]=dcval;
					wsptr[ptr+DCTSIZE*4]=dcval;
					wsptr[ptr+DCTSIZE*5]=dcval;
					wsptr[ptr+DCTSIZE*6]=dcval;
					wsptr[ptr+DCTSIZE*7]=dcval;
					continue;
				}

				// Even part
				int tmp0=inptr[ptr]*quantptr[ptr];
				int tmp1=inptr[ptr+DCTSIZE*2]*quantptr[ptr+DCTSIZE*2];
				int tmp2=inptr[ptr+DCTSIZE*4]*quantptr[ptr+DCTSIZE*4];
				int tmp3=inptr[ptr+DCTSIZE*6]*quantptr[ptr+DCTSIZE*6];

				int tmp10=tmp0+tmp2;	// phase 3
				int tmp11=tmp0-tmp2;

				int tmp13=tmp1+tmp3;	// phases 5-3
				int tmp12=(((tmp1-tmp3)*FIX_1_414213562)>>8)-tmp13; // 2*c4

				tmp0=tmp10+tmp13;		// phase 2
				tmp3=tmp10-tmp13;
				tmp1=tmp11+tmp12;
				tmp2=tmp11-tmp12;

				// Odd part
				int tmp4=inptr[ptr+DCTSIZE*1]*quantptr[ptr+DCTSIZE*1];
				int tmp5=inptr[ptr+DCTSIZE*3]*quantptr[ptr+DCTSIZE*3];
				int tmp6=inptr[ptr+DCTSIZE*5]*quantptr[ptr+DCTSIZE*5];
				int tmp7=inptr[ptr+DCTSIZE*7]*quantptr[ptr+DCTSIZE*7];

				int z13=tmp6+tmp5;		// phase 6
				int z10=tmp6-tmp5;
				int z11=tmp4+tmp7;
				int z12=tmp4-tmp7;

				tmp7=z11+z13;			// phase 5
				tmp11=((z11-z13)*FIX_1_414213562)>>8;	// 2*c4

				int z5=((z10+z12)*FIX_1_847759065)>>8;	// 2*c2
				tmp10=((z12*FIX_1_082392200)>>8)-z5;	// 2*(c2-c6)
				tmp12=((z10*-FIX_2_613125930)>>8)+z5;	// -2*(c2+c6)

				tmp6=tmp12-tmp7;		// phase 2
				tmp5=tmp11-tmp6;
				tmp4=tmp10+tmp5;

				wsptr[ptr]=tmp0+tmp7;
				wsptr[ptr+DCTSIZE*7]=tmp0-tmp7;
				wsptr[ptr+DCTSIZE*1]=tmp1+tmp6;
				wsptr[ptr+DCTSIZE*6]=tmp1-tmp6;
				wsptr[ptr+DCTSIZE*2]=tmp2+tmp5;
				wsptr[ptr+DCTSIZE*5]=tmp2-tmp5;
				wsptr[ptr+DCTSIZE*4]=tmp3+tmp4;
				wsptr[ptr+DCTSIZE*3]=tmp3-tmp4;
			}

			// Pass 2: process rows from work array, store into output array.
			ptr=0;
			for(int ctr=0; ctr<DCTSIZE; ctr++)
			{
				byte[] outptr=output_buf[output_row+ctr];
				// Rows of zeroes can be exploited in the same way as we did with columns.
				// However, the column calculation has created many nonzero AC terms, so
				// the simplification applies less often (typically 5% to 10% of the time).
				// On machines with very fast multiplication, it's possible that the
				// test takes more time than it's worth. In that case this section
				// may be commented out.

#if !NO_ZERO_ROW_TEST
				if(wsptr[ptr+1]==0&&wsptr[ptr+2]==0&&wsptr[ptr+3]==0&&wsptr[ptr+4]==0&&
				wsptr[ptr+5]==0&&wsptr[ptr+6]==0&&wsptr[ptr+7]==0)
				{
					// AC terms all zero
					int dc=CENTERJSAMPLE+(wsptr[ptr]>>5); byte dcval=(byte)((dc>=MAXJSAMPLE)?MAXJSAMPLE:((dc<0)?0:dc));

					outptr[output_col]=dcval;
					outptr[output_col+1]=dcval;
					outptr[output_col+2]=dcval;
					outptr[output_col+3]=dcval;
					outptr[output_col+4]=dcval;
					outptr[output_col+5]=dcval;
					outptr[output_col+6]=dcval;
					outptr[output_col+7]=dcval;

					ptr+=DCTSIZE;		// advance pointer to next row
					continue;
				}
#endif

				// Even part
				int tmp10=wsptr[ptr]+wsptr[ptr+4];
				int tmp11=wsptr[ptr]-wsptr[ptr+4];

				int tmp13=wsptr[ptr+2]+wsptr[ptr+6];
				int tmp12=(((wsptr[ptr+2]-wsptr[ptr+6])*FIX_1_414213562)>>8)-tmp13;

				int tmp0=tmp10+tmp13;
				int tmp3=tmp10-tmp13;
				int tmp1=tmp11+tmp12;
				int tmp2=tmp11-tmp12;

				// Odd part
				int z13=wsptr[ptr+5]+wsptr[ptr+3];
				int z10=wsptr[ptr+5]-wsptr[ptr+3];
				int z11=wsptr[ptr+1]+wsptr[ptr+7];
				int z12=wsptr[ptr+1]-wsptr[ptr+7];

				int tmp7=z11+z13;		// phase 5
				tmp11=((z11-z13)*FIX_1_414213562)>>8;	// 2*c4

				int z5=((z10+z12)*FIX_1_847759065)>>8;	// 2*c2
				tmp10=((z12*FIX_1_082392200)>>8)-z5;	// 2*(c2-c6)
				tmp12=((z10*-FIX_2_613125930)>>8)+z5;	// -2*(c2+c6)

				int tmp6=tmp12-tmp7;	// phase 2
				int tmp5=tmp11-tmp6;
				int tmp4=tmp10+tmp5;

				// Final output stage: scale down by a factor of 8 and range-limit
				int x;
				x=CENTERJSAMPLE+((tmp0+tmp7)>>5); outptr[output_col+0]=(byte)((x>=MAXJSAMPLE)?MAXJSAMPLE:((x<0)?0:x));
				x=CENTERJSAMPLE+((tmp0-tmp7)>>5); outptr[output_col+7]=(byte)((x>=MAXJSAMPLE)?MAXJSAMPLE:((x<0)?0:x));
				x=CENTERJSAMPLE+((tmp1+tmp6)>>5); outptr[output_col+1]=(byte)((x>=MAXJSAMPLE)?MAXJSAMPLE:((x<0)?0:x));
				x=CENTERJSAMPLE+((tmp1-tmp6)>>5); outptr[output_col+6]=(byte)((x>=MAXJSAMPLE)?MAXJSAMPLE:((x<0)?0:x));
				x=CENTERJSAMPLE+((tmp2+tmp5)>>5); outptr[output_col+2]=(byte)((x>=MAXJSAMPLE)?MAXJSAMPLE:((x<0)?0:x));
				x=CENTERJSAMPLE+((tmp2-tmp5)>>5); outptr[output_col+5]=(byte)((x>=MAXJSAMPLE)?MAXJSAMPLE:((x<0)?0:x));
				x=CENTERJSAMPLE+((tmp3+tmp4)>>5); outptr[output_col+4]=(byte)((x>=MAXJSAMPLE)?MAXJSAMPLE:((x<0)?0:x));
				x=CENTERJSAMPLE+((tmp3-tmp4)>>5); outptr[output_col+3]=(byte)((x>=MAXJSAMPLE)?MAXJSAMPLE:((x<0)?0:x));

				ptr+=DCTSIZE;		// advance pointer to next row
			}
		}