Exemplo n.º 1
0
        public const int SAVED_COEFS = 6;               // we save coef_bits[0..5]

        // Reset within-iMCU-row counters for a new row (input side)
        static void start_iMCU_row_d_coef(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;
            d_coef_controller  coef   = (d_coef_controller)lossyd.coef_private;

            // 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 (cinfo.comps_in_scan > 1)
            {
                coef.MCU_rows_per_iMCU_row = 1;
            }
            else
            {
                if (cinfo.input_iMCU_row < (cinfo.total_iMCU_rows - 1))
                {
                    coef.MCU_rows_per_iMCU_row = cinfo.cur_comp_info[0].v_samp_factor;
                }
                else
                {
                    coef.MCU_rows_per_iMCU_row = cinfo.cur_comp_info[0].last_row_height;
                }
            }

            coef.MCU_ctr         = 0;
            coef.MCU_vert_offset = 0;
        }
Exemplo n.º 2
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;
            }
        }
Exemplo n.º 3
0
        // Initialize for an output processing pass.
        static void start_output_pass_lossy(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;

            lossyd.idct_start_pass(cinfo);
            lossyd.coef_start_output_pass(cinfo);
        }
Exemplo n.º 4
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;
        }
Exemplo n.º 5
0
        // Initialize for an input processing pass.
        static void start_input_pass_lossy(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;

            latch_quant_tables_lossy(cinfo);
            lossyd.entropy_start_pass(cinfo);
            lossyd.coef_start_input_pass(cinfo);
        }
Exemplo n.º 6
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
            }
        }
Exemplo n.º 7
0
        // Module initialization routine for progressive Huffman entropy decoding.
        public static void jinit_phuff_decoder(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec    lossyd  = (jpeg_lossy_d_codec)cinfo.coef;
            phuff_entropy_decoder entropy = null;

            try
            {
                entropy = new phuff_entropy_decoder();
                entropy.saved.last_dc_val = new int[MAX_COMPS_IN_SCAN];
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }
            lossyd.entropy_private    = entropy;
            lossyd.entropy_start_pass = start_pass_phuff_decoder;

            // Mark derived tables unallocated
            for (int i = 0; i < NUM_HUFF_TBLS; i++)
            {
                entropy.derived_tbls[i] = null;
            }

            try
            {
                // Create progression status table
                cinfo.coef_bits = new int[cinfo.num_components][];

                for (int ci = 0; ci < cinfo.num_components; ci++)
                {
                    int[] coef_bit_ptr = cinfo.coef_bits[ci] = new int[DCTSIZE2];
                    for (int i = 0; i < DCTSIZE2; i++)
                    {
                        coef_bit_ptr[i] = -1;
                    }
                }
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }
        }
Exemplo n.º 8
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;
                }
            }
        }
Exemplo n.º 9
0
        // Initialize for an output processing pass.
        static void start_output_pass_d_coef(jpeg_decompress cinfo)
        {
#if BLOCK_SMOOTHING_SUPPORTED
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;
            d_coef_controller  coef   = (d_coef_controller)lossyd.coef_private;

            // If multipass, check to see whether to use block smoothing on this pass
            if (lossyd.coef_arrays != null)
            {
                if (cinfo.do_block_smoothing && smoothing_ok(cinfo))
                {
                    lossyd.decompress_data = decompress_smooth_data;
                }
                else
                {
                    lossyd.decompress_data = decompress_data;
                }
            }
#endif
            cinfo.output_iMCU_row = 0;
        }
Exemplo n.º 10
0
        //#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))

        // Check for a restart marker & resynchronize decoder.
        // Returns false if must suspend.
        static bool process_restart_dphuff(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec    lossyd  = (jpeg_lossy_d_codec)cinfo.coef;
            phuff_entropy_decoder entropy = (phuff_entropy_decoder)lossyd.entropy_private;

            // Throw away any unused bits remaining in bit buffer;
            // include any full bytes in next_marker's count of discarded bytes
            cinfo.marker.discarded_bytes += (uint)(entropy.bitstate.bits_left / 8);
            entropy.bitstate.bits_left    = 0;

            // Advance past the RSTn marker
            if (!cinfo.marker.read_restart_marker(cinfo))
            {
                return(false);
            }

            // Re-initialize DC predictions to 0
            for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
            {
                entropy.saved.last_dc_val[ci] = 0;
            }

            // Re-init EOB run count, too
            entropy.saved.EOBRUN = 0;

            // Reset restart counter
            entropy.restarts_to_go = cinfo.restart_interval;

            // Reset out-of-data flag, unless read_restart_marker left us smack up
            // against a marker. In that case we will end up treating the next data
            // segment as empty, and we can avoid producing bogus output pixels by
            // leaving the flag set.
            if (cinfo.unread_marker == 0)
            {
                entropy.insufficient_data = false;
            }

            return(true);
        }
Exemplo n.º 11
0
        // Module initialization routine for Huffman entropy decoding.
        public static void jinit_shuff_decoder(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec    lossyd  = (jpeg_lossy_d_codec)cinfo.coef;
            shuff_entropy_decoder entropy = null;

            try
            {
                entropy = new shuff_entropy_decoder();
                entropy.saved.last_dc_val = new int[MAX_COMPS_IN_SCAN];
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }
            lossyd.entropy_private    = entropy;
            lossyd.entropy_start_pass = start_pass_huff_decoder;
            lossyd.entropy_decode_mcu = decode_mcu;

            // Mark tables unallocated
            for (int i = 0; i < NUM_HUFF_TBLS; i++)
            {
                entropy.dc_derived_tbls[i] = entropy.ac_derived_tbls[i] = null;
            }
        }
Exemplo n.º 12
0
        // MCU decoding for AC initial scan (either spectral selection,
        // or first pass of successive approximation).
        static bool decode_mcu_AC_first(jpeg_decompress cinfo, short[][] MCU_data)
        {
            jpeg_lossy_d_codec    lossyd  = (jpeg_lossy_d_codec)cinfo.coef;
            phuff_entropy_decoder entropy = (phuff_entropy_decoder)lossyd.entropy_private;
            int Se = cinfo.Se;
            int Al = cinfo.Al;

            // Process restart marker if needed; may have to suspend
            if (cinfo.restart_interval != 0)
            {
                if (entropy.restarts_to_go == 0)
                {
                    if (!process_restart_dphuff(cinfo))
                    {
                        return(false);
                    }
                }
            }

            // If we've run out of data, just leave the MCU set to zeroes.
            // This way, we return uniform gray for the remainder of the segment.
            if (!entropy.insufficient_data)
            {
                // Load up working state.
                // We can avoid loading/saving bitread state if in an EOB run.
                uint EOBRUN = entropy.saved.EOBRUN;               // only part of saved state we need

                // There is always only one block per MCU
                if (EOBRUN > 0)
                {
                    EOBRUN--;                          // if it's a band of zeroes... ...process it now (we do nothing)
                }
                else
                {
                    //was BITREAD_STATE_VARS;
                    bitread_working_state br_state = new bitread_working_state();

                    //was BITREAD_LOAD_STATE(cinfo, entropy.bitstate);
                    br_state.cinfo           = cinfo;
                    br_state.input_bytes     = cinfo.src.input_bytes;
                    br_state.next_input_byte = cinfo.src.next_input_byte;
                    br_state.bytes_in_buffer = cinfo.src.bytes_in_buffer;
                    ulong         get_buffer = entropy.bitstate.get_buffer;
                    int           bits_left  = entropy.bitstate.bits_left;
                    short[]       block      = MCU_data[0];
                    d_derived_tbl tbl        = entropy.ac_derived_tbl;

                    for (int k = cinfo.Ss; k <= Se; k++)
                    {
                        int s = 0, r;

                        //was HUFF_DECODE(s, br_state, tbl, return false, label2);
                        {
                            int  nb, look;
                            bool label = false;
                            if (bits_left < HUFF_LOOKAHEAD)
                            {
                                if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0))
                                {
                                    return(false);
                                }
                                get_buffer = br_state.get_buffer;
                                bits_left  = br_state.bits_left;
                                if (bits_left < HUFF_LOOKAHEAD)
                                {
                                    nb    = 1;
                                    label = true;
                                    if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb)) < 0)
                                    {
                                        return(false);
                                    }
                                    get_buffer = br_state.get_buffer;
                                    bits_left  = br_state.bits_left;
                                }
                            }

                            if (!label)
                            {
                                //was look=PEEK_BITS(HUFF_LOOKAHEAD);
                                look = ((int)(get_buffer >> (bits_left - HUFF_LOOKAHEAD))) & ((1 << HUFF_LOOKAHEAD) - 1);
                                if ((nb = tbl.look_nbits[look]) != 0)
                                {
                                    //was DROP_BITS(nb);
                                    bits_left -= nb;
                                    s          = tbl.look_sym[look];
                                }
                                else
                                {
                                    nb = HUFF_LOOKAHEAD + 1;
                                    if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb)) < 0)
                                    {
                                        return(false);
                                    }
                                    get_buffer = br_state.get_buffer;
                                    bits_left  = br_state.bits_left;
                                }
                            }
                        }

                        r  = s >> 4;
                        s &= 15;
                        if (s != 0)
                        {
                            k += r;
                            //was CHECK_BIT_BUFFER(br_state, s, return false);
                            if (bits_left < s)
                            {
                                if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s))
                                {
                                    return(false);
                                }
                                get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                            }
                            //was r = GET_BITS(s);
                            r = ((int)(get_buffer >> (bits_left -= s))) & ((1 << s) - 1);
                            //was s=HUFF_EXTEND(r, s);
                            s = (r < (1 << (s - 1))?r + (((-1) << s) + 1):r);

                            // Scale and output coefficient in natural (dezigzagged) order
                            block[jpeg_natural_order[k]] = (short)(s << Al);
                        }
                        else
                        {
                            if (r == 15)
                            {                             // ZRL
                                k += 15;                  // skip 15 zeroes in band
                            }
                            else
                            {                             // EOBr, run length is 2^r + appended bits
                                EOBRUN = (uint)(1 << r);
                                if (r != 0)
                                {                                 // EOBr, r > 0
                                    //was CHECK_BIT_BUFFER(br_state, r, return false);
                                    if (bits_left < r)
                                    {
                                        if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, r))
                                        {
                                            return(false);
                                        }
                                        get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                                    }
                                    //was r = GET_BITS(r);
                                    r       = ((int)(get_buffer >> (bits_left -= r))) & ((1 << r) - 1);
                                    EOBRUN += (uint)r;
                                }
                                EOBRUN--;                                       // this band is processed at this moment
                                break;                                          // force end-of-band
                            }
                        }
                    }

                    //was BITREAD_SAVE_STATE(cinfo, entropy.bitstate);
                    cinfo.src.input_bytes       = br_state.input_bytes;
                    cinfo.src.next_input_byte   = br_state.next_input_byte;
                    cinfo.src.bytes_in_buffer   = br_state.bytes_in_buffer;
                    entropy.bitstate.get_buffer = get_buffer;
                    entropy.bitstate.bits_left  = bits_left;
                }

                // Completed MCU, so update state
                entropy.saved.EOBRUN = EOBRUN;               // only part of saved state we need
            }

            // Account for restart interval (no-op if not using restarts)
            entropy.restarts_to_go--;

            return(true);
        }
Exemplo n.º 13
0
        // MCU decoding for DC successive approximation refinement scan.
        // Note: we assume such scans can be multi-component, although the spec
        // is not very clear on the point.
        static bool decode_mcu_DC_refine(jpeg_decompress cinfo, short[][] MCU_data)
        {
            jpeg_lossy_d_codec    lossyd  = (jpeg_lossy_d_codec)cinfo.coef;
            phuff_entropy_decoder entropy = (phuff_entropy_decoder)lossyd.entropy_private;
            short p1 = (short)(1 << cinfo.Al);          // 1 in the bit position being coded

            // Process restart marker if needed; may have to suspend
            if (cinfo.restart_interval != 0)
            {
                if (entropy.restarts_to_go == 0)
                {
                    if (!process_restart_dphuff(cinfo))
                    {
                        return(false);
                    }
                }
            }

            // Not worth the cycles to check insufficient_data here,
            // since we will not change the data anyway if we read zeroes.

            // Load up working state
            //was BITREAD_STATE_VARS;
            bitread_working_state br_state = new bitread_working_state();

            //was BITREAD_LOAD_STATE(cinfo, entropy.bitstate);
            br_state.cinfo           = cinfo;
            br_state.input_bytes     = cinfo.src.input_bytes;
            br_state.next_input_byte = cinfo.src.next_input_byte;
            br_state.bytes_in_buffer = cinfo.src.bytes_in_buffer;
            ulong get_buffer = entropy.bitstate.get_buffer;
            int   bits_left  = entropy.bitstate.bits_left;

            // Outer loop handles each block in the MCU
            for (int blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++)
            {
                short[] block = MCU_data[blkn];

                // Encoded data is simply the next bit of the two's-complement DC value
                //was CHECK_BIT_BUFFER(br_state, 1, return false);
                if (bits_left < 1)
                {
                    if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1))
                    {
                        return(false);
                    }
                    get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                }

                //was if(GET_BITS(1))
                if ((((int)(get_buffer >> (bits_left -= 1))) & 1) != 0)
                {
                    block[0] |= p1;
                }
                // Note: since we use |=, repeating the assignment later is safe
            }

            // Completed MCU, so update state
            //was BITREAD_SAVE_STATE(cinfo, entropy.bitstate);
            cinfo.src.input_bytes       = br_state.input_bytes;
            cinfo.src.next_input_byte   = br_state.next_input_byte;
            cinfo.src.bytes_in_buffer   = br_state.bytes_in_buffer;
            entropy.bitstate.get_buffer = get_buffer;
            entropy.bitstate.bits_left  = bits_left;

            // Account for restart interval (no-op if not using restarts)
            entropy.restarts_to_go--;

            return(true);
        }
Exemplo n.º 14
0
		// Initialize the lossy decompression codec.
		// This is called only once, during master selection.
		static void jinit_lossy_d_codec(jpeg_decompress cinfo)
		{
			jpeg_lossy_d_codec lossyd=null;

			// Create subobject
			try
			{
				if(cinfo.arith_code)
				{
#if D_ARITH_CODING_SUPPORTED
					lossyd=new arith_entropy_decoder();
#else
					ERREXIT(cinfo, J_MESSAGE_CODE.JERR_ARITH_NOTIMPL);
#endif
				}
				else lossyd=new jpeg_lossy_d_codec();
			}
			catch
			{
				ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
			}

			cinfo.coef=lossyd;

			// Initialize sub-modules

			// Inverse DCT
			jinit_inverse_dct(cinfo);

			// Entropy decoding: either Huffman or arithmetic coding.
			if(cinfo.arith_code)
			{
#if D_ARITH_CODING_SUPPORTED
				jinit_arith_decoder(cinfo);
#else
				ERREXIT(cinfo, J_MESSAGE_CODE.JERR_ARITH_NOTIMPL);
#endif
			}
			else
			{
				if(cinfo.process==J_CODEC_PROCESS.JPROC_PROGRESSIVE)
				{
#if D_PROGRESSIVE_SUPPORTED
					jinit_phuff_decoder(cinfo);
#else
					ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED);
#endif
				}
				else jinit_shuff_decoder(cinfo);
			}

			bool use_c_buffer=cinfo.inputctl.has_multiple_scans||cinfo.buffered_image;
			jinit_d_coef_controller(cinfo, use_c_buffer);

			// Initialize method pointers.
			//
			// Note: consume_data and decompress_data are assigned in jdcoefct.cs.
			lossyd.calc_output_dimensions=calc_output_dimensions_lossy;
			lossyd.start_input_pass=start_input_pass_lossy;
			lossyd.start_output_pass=start_output_pass_lossy;
		}
Exemplo n.º 15
0
        // Initialize the lossy decompression codec.
        // This is called only once, during master selection.
        static void jinit_lossy_d_codec(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec lossyd = null;

            // Create subobject
            try
            {
                if (cinfo.arith_code)
                {
#if D_ARITH_CODING_SUPPORTED
                    lossyd = new arith_entropy_decoder();
#else
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_ARITH_NOTIMPL);
#endif
                }
                else
                {
                    lossyd = new jpeg_lossy_d_codec();
                }
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }

            cinfo.coef = lossyd;

            // Initialize sub-modules

            // Inverse DCT
            jinit_inverse_dct(cinfo);

            // Entropy decoding: either Huffman or arithmetic coding.
            if (cinfo.arith_code)
            {
#if D_ARITH_CODING_SUPPORTED
                jinit_arith_decoder(cinfo);
#else
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_ARITH_NOTIMPL);
#endif
            }
            else
            {
                if (cinfo.process == J_CODEC_PROCESS.JPROC_PROGRESSIVE)
                {
#if D_PROGRESSIVE_SUPPORTED
                    jinit_phuff_decoder(cinfo);
#else
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED);
#endif
                }
                else
                {
                    jinit_shuff_decoder(cinfo);
                }
            }

            bool use_c_buffer = cinfo.inputctl.has_multiple_scans || cinfo.buffered_image;
            jinit_d_coef_controller(cinfo, use_c_buffer);

            // Initialize method pointers.
            //
            // Note: consume_data and decompress_data are assigned in jdcoefct.cs.
            lossyd.calc_output_dimensions = calc_output_dimensions_lossy;
            lossyd.start_input_pass       = start_input_pass_lossy;
            lossyd.start_output_pass      = start_output_pass_lossy;
        }
Exemplo n.º 16
0
        // MCU decoding for AC successive approximation refinement scan.
        static bool decode_mcu_AC_refine(jpeg_decompress cinfo, short[][] MCU_data)
        {
            jpeg_lossy_d_codec    lossyd  = (jpeg_lossy_d_codec)cinfo.coef;
            phuff_entropy_decoder entropy = (phuff_entropy_decoder)lossyd.entropy_private;
            int   Se = cinfo.Se;
            short p1 = (short)(1 << cinfo.Al);                  // 1 in the bit position being coded
            short m1 = (short)((-1) << cinfo.Al);               // -1 in the bit position being coded

            short[] block = null;

            // If we are forced to suspend, we must undo the assignments to any newly
            // nonzero coefficients in the block, because otherwise we'd get confused
            // next time about which coefficients were already nonzero.
            // But we need not undo addition of bits to already-nonzero coefficients;
            // instead, we can test the current bit to see if we already did it.
            int num_newnz = 0;

            int[] newnz_pos = new int[DCTSIZE2];

            // Process restart marker if needed; may have to suspend
            if (cinfo.restart_interval != 0)
            {
                if (entropy.restarts_to_go == 0)
                {
                    if (!process_restart_dphuff(cinfo))
                    {
                        return(false);
                    }
                }
            }

            // If we've run out of data, don't modify the MCU.
            if (!entropy.insufficient_data)
            {
                // Load up working state
                //was BITREAD_STATE_VARS;
                bitread_working_state br_state = new bitread_working_state();

                //was BITREAD_LOAD_STATE(cinfo, entropy.bitstate);
                br_state.cinfo           = cinfo;
                br_state.input_bytes     = cinfo.src.input_bytes;
                br_state.next_input_byte = cinfo.src.next_input_byte;
                br_state.bytes_in_buffer = cinfo.src.bytes_in_buffer;
                ulong get_buffer = entropy.bitstate.get_buffer;
                int   bits_left  = entropy.bitstate.bits_left;
                uint  EOBRUN     = entropy.saved.EOBRUN;          // only part of saved state we need

                // There is always only one block per MCU
                block = MCU_data[0];
                d_derived_tbl tbl = entropy.ac_derived_tbl;

                // initialize coefficient loop counter to start of band
                int k = cinfo.Ss;

                if (EOBRUN == 0)
                {
                    for (; k <= Se; k++)
                    {
                        int s = 0, r;

                        //was HUFF_DECODE(s, br_state, tbl, goto undoit, label3);
                        {
                            int  nb, look;
                            bool label = false;
                            if (bits_left < HUFF_LOOKAHEAD)
                            {
                                if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0))
                                {
                                    goto undoit;
                                }
                                get_buffer = br_state.get_buffer;
                                bits_left  = br_state.bits_left;
                                if (bits_left < HUFF_LOOKAHEAD)
                                {
                                    nb    = 1;
                                    label = true;
                                    if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb)) < 0)
                                    {
                                        goto undoit;
                                    }
                                    get_buffer = br_state.get_buffer;
                                    bits_left  = br_state.bits_left;
                                }
                            }

                            if (!label)
                            {
                                //was look=PEEK_BITS(HUFF_LOOKAHEAD);
                                look = ((int)(get_buffer >> (bits_left - HUFF_LOOKAHEAD))) & ((1 << HUFF_LOOKAHEAD) - 1);
                                if ((nb = tbl.look_nbits[look]) != 0)
                                {
                                    //was DROP_BITS(nb);
                                    bits_left -= nb;
                                    s          = tbl.look_sym[look];
                                }
                                else
                                {
                                    nb = HUFF_LOOKAHEAD + 1;
                                    if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb)) < 0)
                                    {
                                        goto undoit;
                                    }
                                    get_buffer = br_state.get_buffer;
                                    bits_left  = br_state.bits_left;
                                }
                            }
                        }

                        r  = s >> 4;
                        s &= 15;
                        if (s != 0)
                        {
                            if (s != 1)
                            {
                                WARNMS(cinfo, J_MESSAGE_CODE.JWRN_HUFF_BAD_CODE);                                  // size of new coef should always be 1
                            }
                            //was CHECK_BIT_BUFFER(br_state, 1, goto undoit);
                            if (bits_left < 1)
                            {
                                if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1))
                                {
                                    goto undoit;
                                }
                                get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                            }
                            //was if (GET_BITS(1))
                            if ((((int)(get_buffer >> (bits_left -= 1))) & 1) != 0)
                            {
                                s = p1;                                                                      // newly nonzero coef is positive
                            }
                            else
                            {
                                s = m1;                            // newly nonzero coef is negative
                            }
                        }
                        else
                        {
                            if (r != 15)
                            {
                                EOBRUN = (uint)(1 << r);                             // EOBr, run length is 2^r + appended bits
                                if (r != 0)
                                {
                                    //was CHECK_BIT_BUFFER(br_state, r, goto undoit);
                                    if (bits_left < r)
                                    {
                                        if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, r))
                                        {
                                            goto undoit;
                                        }
                                        get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                                    }
                                    //was r = GET_BITS(r);
                                    r       = ((int)(get_buffer >> (bits_left -= r))) & ((1 << r) - 1);
                                    EOBRUN += (uint)r;
                                }
                                break;                                 // rest of block is handled by EOB logic
                            }
                            // note s = 0 for processing ZRL
                        }
                        // Advance over already-nonzero coefs and r still-zero coefs,
                        // appending correction bits to the nonzeroes. A correction bit is 1
                        // if the absolute value of the coefficient must be increased.
                        do
                        {
                            int thiscoef = jpeg_natural_order[k];
                            if (block[thiscoef] != 0)
                            {
                                //was CHECK_BIT_BUFFER(br_state, 1, goto undoit);
                                if (bits_left < 1)
                                {
                                    if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1))
                                    {
                                        goto undoit;
                                    }
                                    get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                                }
                                //was if (GET_BITS(1))
                                if ((((int)(get_buffer >> (bits_left -= 1))) & 1) != 0)
                                {
                                    if ((block[thiscoef] & p1) == 0)
                                    {                                     // do nothing if already set it
                                        if (block[thiscoef] >= 0)
                                        {
                                            block[thiscoef] += p1;
                                        }
                                        else
                                        {
                                            block[thiscoef] += m1;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                if (--r < 0)
                                {
                                    break;                                       // reached target zero coefficient
                                }
                            }
                            k++;
                        } while(k <= Se);

                        if (s != 0)
                        {
                            int pos = jpeg_natural_order[k];
                            // Output newly nonzero coefficient
                            block[pos] = (short)s;
                            // Remember its position in case we have to suspend
                            newnz_pos[num_newnz++] = pos;
                        }
                    }
                }

                if (EOBRUN > 0)
                {
                    // Scan any remaining coefficient positions after the end-of-band
                    // (the last newly nonzero coefficient, if any). Append a correction
                    // bit to each already-nonzero coefficient. A correction bit is 1
                    // if the absolute value of the coefficient must be increased.
                    for (; k <= Se; k++)
                    {
                        int thiscoef = jpeg_natural_order[k];
                        if (block[thiscoef] != 0)
                        {
                            //was CHECK_BIT_BUFFER(br_state, 1, goto undoit);
                            if (bits_left < 1)
                            {
                                if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 1))
                                {
                                    goto undoit;
                                }
                                get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                            }
                            //was if (GET_BITS(1))
                            if ((((int)(get_buffer >> (bits_left -= 1))) & 1) != 0)
                            {
                                if ((block[thiscoef] & p1) == 0)
                                {                                 // do nothing if already changed it
                                    if (block[thiscoef] >= 0)
                                    {
                                        block[thiscoef] += p1;
                                    }
                                    else
                                    {
                                        block[thiscoef] += m1;
                                    }
                                }
                            }
                        }
                    }
                    // Count one block completed in EOB run
                    EOBRUN--;
                }

                // Completed MCU, so update state
                //was BITREAD_SAVE_STATE(cinfo, entropy.bitstate);
                cinfo.src.input_bytes       = br_state.input_bytes;
                cinfo.src.next_input_byte   = br_state.next_input_byte;
                cinfo.src.bytes_in_buffer   = br_state.bytes_in_buffer;
                entropy.bitstate.get_buffer = get_buffer;
                entropy.bitstate.bits_left  = bits_left;
                entropy.saved.EOBRUN        = EOBRUN;        // only part of saved state we need
            }

            // Account for restart interval (no-op if not using restarts)
            entropy.restarts_to_go--;

            return(true);

undoit:
            // Re-zero any output coefficients that we made newly nonzero
            while (num_newnz > 0)
            {
                block[newnz_pos[--num_newnz]] = 0;
            }

            return(false);
        }
Exemplo n.º 17
0
        // Decompress and return some data in the single-pass case.
        // Always attempts to emit one fully interleaved MCU row ("iMCU" row).
        // Input and output must run in lockstep since we have only a one-MCU buffer.
        // Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
        //
        // NB: output_buf contains a plane for each component in image,
        // which we index according to the component's SOF position.
        static CONSUME_INPUT decompress_onepass(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;

            uint last_MCU_col  = cinfo.MCUs_per_row - 1;
            uint last_iMCU_row = cinfo.total_iMCU_rows - 1;

            // Loop to process as much as 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 <= last_MCU_col; MCU_col_num++)            // index of current MCU within row
                {
                    // Try to fetch an MCU. Entropy decoder expects buffer to be zeroed.
                    for (int i = 0; i < cinfo.blocks_in_MCU; i++)
                    {
                        for (int a = 0; a < DCTSIZE2; a++)
                        {
                            coef.MCU_buffer[i][a] = 0;
                        }
                    }

                    if (!lossyd.entropy_decode_mcu(cinfo, coef.MCU_buffer))
                    {
                        // Suspension forced; update state counters and exit
                        coef.MCU_vert_offset = yoffset;
                        coef.MCU_ctr         = MCU_col_num;
                        return(CONSUME_INPUT.JPEG_SUSPENDED);
                    }

                    // Determine where data should go in output_buf and do the IDCT thing.
                    // We skip dummy blocks at the right and bottom edges (but blkn gets
                    // incremented past them!). Note the inner loop relies on having
                    // allocated the MCU_buffer[] blocks sequentially.
                    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];

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

                        inverse_DCT_method_ptr inverse_DCT = lossyd.inverse_DCT[compptr.component_index];

                        int useful_width = (MCU_col_num < last_MCU_col)?compptr.MCU_width:compptr.last_col_width;

                        byte[][] output_ptr     = output_buf[compptr.component_index];
                        uint     output_ptr_ind = (uint)yoffset * compptr.DCT_scaled_size;

                        uint start_col = MCU_col_num * (uint)compptr.MCU_sample_width;

                        for (int yindex = 0; yindex < compptr.MCU_height; yindex++)
                        {
                            if (cinfo.input_iMCU_row < last_iMCU_row || yoffset + yindex < compptr.last_row_height)
                            {
                                uint output_col = start_col;
                                for (int xindex = 0; xindex < useful_width; xindex++)
                                {
                                    inverse_DCT(cinfo, compptr, coef.MCU_buffer[blkn + xindex], output_ptr, output_ptr_ind, output_col);
                                    output_col += compptr.DCT_scaled_size;
                                }
                            }
                            blkn           += compptr.MCU_width;
                            output_ptr_ind += compptr.DCT_scaled_size;
                        }
                    }
                }

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

            // Completed the iMCU row, advance counters for next one
            cinfo.output_iMCU_row++;
            if (++(cinfo.input_iMCU_row) < cinfo.total_iMCU_rows)
            {
                start_iMCU_row_d_coef(cinfo);
                return(CONSUME_INPUT.JPEG_ROW_COMPLETED);
            }

            // Completed the scan
            cinfo.inputctl.finish_input_pass(cinfo);
            return(CONSUME_INPUT.JPEG_SCAN_COMPLETED);
        }
Exemplo n.º 18
0
        // Consume input data and store it in the full-image coefficient buffer.
        // We read as much as one fully interleaved MCU row ("iMCU" row) per call,
        // ie, v_samp_factor block rows for each component in the scan.
        // Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
        static CONSUME_INPUT consume_data(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;
            d_coef_controller  coef   = (d_coef_controller)lossyd.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.
            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)cinfo.input_iMCU_row * compptr.v_samp_factor;
                // Note: entropy decoder expects buffer to be zeroed,
                // but this is handled automatically by the memory manager
                // because we requested a pre-zeroed array.
            }

            // 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++)            // index of current MCU within row
                {
                    // 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 fetch the MCU.
                    if (!lossyd.entropy_decode_mcu(cinfo, coef.MCU_buffer))
                    {
                        // Suspension forced; update state counters and exit
                        coef.MCU_vert_offset = yoffset;
                        coef.MCU_ctr         = MCU_col_num;
                        return(CONSUME_INPUT.JPEG_SUSPENDED);
                    }
                }

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

            // Completed the iMCU row, advance counters for next one
            if (++(cinfo.input_iMCU_row) < cinfo.total_iMCU_rows)
            {
                start_iMCU_row_d_coef(cinfo);
                return(CONSUME_INPUT.JPEG_ROW_COMPLETED);
            }

            // Completed the scan
            cinfo.inputctl.finish_input_pass(cinfo);
            return(CONSUME_INPUT.JPEG_SCAN_COMPLETED);
        }
Exemplo n.º 19
0
        // Decode and return one MCU's worth of Huffman-compressed coefficients.
        // The coefficients are reordered from zigzag order into natural array order,
        // but are not dequantized.
        //
        // The i'th block of the MCU is stored into the block pointed to by
        // MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER.
        // (Wholesale zeroing is usually a little faster than retail...)
        //
        // Returns false if data source requested suspension. In that case no
        // changes have been made to permanent state. (Exception: some output
        // coefficients may already have been assigned. This is harmless for
        // this module, since we'll just re-assign them on the next call.)
        static bool decode_mcu(jpeg_decompress cinfo, short[][] MCU_data)
        {
            jpeg_lossy_d_codec    lossyd  = (jpeg_lossy_d_codec)cinfo.coef;
            shuff_entropy_decoder entropy = (shuff_entropy_decoder)lossyd.entropy_private;

            // Process restart marker if needed; may have to suspend
            if (cinfo.restart_interval != 0)
            {
                if (entropy.restarts_to_go == 0)
                {
                    if (!process_restart_dshuff(cinfo))
                    {
                        return(false);
                    }
                }
            }

            // If we've run out of data, just leave the MCU set to zeroes.
            // This way, we return uniform gray for the remainder of the segment.
            if (!entropy.insufficient_data)
            {
                bitread_working_state br_state = new bitread_working_state();

                savable_state_sq state;
                state.last_dc_val = new int[MAX_COMPS_IN_SCAN];

                // Load up working state
                //was BITREAD_STATE_VARS;
                //was BITREAD_LOAD_STATE(cinfo, entropy.bitstate);
                br_state.cinfo           = cinfo;
                br_state.input_bytes     = cinfo.src.input_bytes;
                br_state.next_input_byte = cinfo.src.next_input_byte;
                br_state.bytes_in_buffer = cinfo.src.bytes_in_buffer;
                ulong get_buffer = entropy.bitstate.get_buffer;
                int   bits_left  = entropy.bitstate.bits_left;

                //was state=entropy.saved;
                entropy.saved.last_dc_val.CopyTo(state.last_dc_val, 0);

                // Outer loop handles each block in the MCU
                for (int blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++)
                {
                    short[]       block = MCU_data[blkn];
                    d_derived_tbl dctbl = entropy.dc_cur_tbls[blkn];
                    d_derived_tbl actbl = entropy.ac_cur_tbls[blkn];
                    int           s = 0, k, r;

                    // Decode a single block's worth of coefficients

                    // Section F.2.2.1: decode the DC coefficient difference
                    //was HUFF_DECODE(s, br_state, dctbl, return false, label1);
                    {
                        int  nb, look;
                        bool label = false;
                        if (bits_left < HUFF_LOOKAHEAD)
                        {
                            if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0))
                            {
                                return(false);
                            }
                            get_buffer = br_state.get_buffer;
                            bits_left  = br_state.bits_left;
                            if (bits_left < HUFF_LOOKAHEAD)
                            {
                                nb    = 1;
                                label = true;
                                if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, dctbl, nb)) < 0)
                                {
                                    return(false);
                                }
                                get_buffer = br_state.get_buffer;
                                bits_left  = br_state.bits_left;
                            }
                        }

                        if (!label)
                        {
                            //was look=PEEK_BITS(HUFF_LOOKAHEAD);
                            look = ((int)(get_buffer >> (bits_left - HUFF_LOOKAHEAD))) & ((1 << HUFF_LOOKAHEAD) - 1);
                            if ((nb = dctbl.look_nbits[look]) != 0)
                            {
                                //was DROP_BITS(nb);
                                bits_left -= nb;
                                s          = dctbl.look_sym[look];
                            }
                            else
                            {
                                nb = HUFF_LOOKAHEAD + 1;
                                if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, dctbl, nb)) < 0)
                                {
                                    return(false);
                                }
                                get_buffer = br_state.get_buffer;
                                bits_left  = br_state.bits_left;
                            }
                        }
                    }

                    if (s != 0)
                    {
                        //was CHECK_BIT_BUFFER(br_state, s, return false);
                        if (bits_left < s)
                        {
                            if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s))
                            {
                                return(false);
                            }
                            get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                        }
                        //was r = GET_BITS(s);
                        r = ((int)(get_buffer >> (bits_left -= s))) & ((1 << s) - 1);
                        //was s=HUFF_EXTEND(r, s);
                        s = (r < (1 << (s - 1))?r + (((-1) << s) + 1):r);
                    }

                    if (entropy.dc_needed[blkn])
                    {
                        // Convert DC difference to actual value, update last_dc_val
                        int ci = cinfo.MCU_membership[blkn];
                        s += state.last_dc_val[ci];
                        state.last_dc_val[ci] = s;
                        // Output the DC coefficient (assumes jpeg_natural_order[0] = 0)
                        block[0] = (short)s;
                    }

                    if (entropy.ac_needed[blkn])
                    {
                        // Section F.2.2.2: decode the AC coefficients
                        // Since zeroes are skipped, output area must be cleared beforehand
                        for (k = 1; k < DCTSIZE2; k++)
                        {
                            //was HUFF_DECODE(s, br_state, actbl, return false, label2);
                            {
                                int  nb, look;
                                bool label = false;
                                if (bits_left < HUFF_LOOKAHEAD)
                                {
                                    if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0))
                                    {
                                        return(false);
                                    }
                                    get_buffer = br_state.get_buffer;
                                    bits_left  = br_state.bits_left;
                                    if (bits_left < HUFF_LOOKAHEAD)
                                    {
                                        nb    = 1;
                                        label = true;
                                        if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, actbl, nb)) < 0)
                                        {
                                            return(false);
                                        }
                                        get_buffer = br_state.get_buffer;
                                        bits_left  = br_state.bits_left;
                                    }
                                }

                                if (!label)
                                {
                                    //was look=PEEK_BITS(HUFF_LOOKAHEAD);
                                    look = ((int)(get_buffer >> (bits_left - HUFF_LOOKAHEAD))) & ((1 << HUFF_LOOKAHEAD) - 1);
                                    if ((nb = actbl.look_nbits[look]) != 0)
                                    {
                                        //was DROP_BITS(nb);
                                        bits_left -= nb;
                                        s          = actbl.look_sym[look];
                                    }
                                    else
                                    {
                                        nb = HUFF_LOOKAHEAD + 1;
                                        if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, actbl, nb)) < 0)
                                        {
                                            return(false);
                                        }
                                        get_buffer = br_state.get_buffer;
                                        bits_left  = br_state.bits_left;
                                    }
                                }
                            }

                            r  = s >> 4;
                            s &= 15;

                            if (s != 0)
                            {
                                k += r;
                                //was CHECK_BIT_BUFFER(br_state, s, return false);
                                if (bits_left < s)
                                {
                                    if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s))
                                    {
                                        return(false);
                                    }
                                    get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                                }
                                //was r = GET_BITS(s);
                                r = ((int)(get_buffer >> (bits_left -= s))) & ((1 << s) - 1);
                                //was s=HUFF_EXTEND(r, s);
                                s = (r < (1 << (s - 1))?r + (((-1) << s) + 1):r);


                                // Output coefficient in natural (dezigzagged) order.
                                // Note: the extra entries in jpeg_natural_order[] will save us
                                // if k >= DCTSIZE2, which could happen if the data is corrupted.
                                block[jpeg_natural_order[k]] = (short)s;
                            }
                            else
                            {
                                if (r != 15)
                                {
                                    break;
                                }
                                k += 15;
                            }
                        }
                    }
                    else
                    {
                        // Section F.2.2.2: decode the AC coefficients
                        // In this path we just discard the values
                        for (k = 1; k < DCTSIZE2; k++)
                        {
                            //was HUFF_DECODE(s, br_state, actbl, return false, label3);
                            {
                                int  nb, look;
                                bool label = false;
                                if (bits_left < HUFF_LOOKAHEAD)
                                {
                                    if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0))
                                    {
                                        return(false);
                                    }
                                    get_buffer = br_state.get_buffer;
                                    bits_left  = br_state.bits_left;
                                    if (bits_left < HUFF_LOOKAHEAD)
                                    {
                                        nb    = 1;
                                        label = true;
                                        if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, actbl, nb)) < 0)
                                        {
                                            return(false);
                                        }
                                        get_buffer = br_state.get_buffer;
                                        bits_left  = br_state.bits_left;
                                    }
                                }

                                if (!label)
                                {
                                    //was look=PEEK_BITS(HUFF_LOOKAHEAD);
                                    look = ((int)(get_buffer >> (bits_left - HUFF_LOOKAHEAD))) & ((1 << HUFF_LOOKAHEAD) - 1);
                                    if ((nb = actbl.look_nbits[look]) != 0)
                                    {
                                        //was DROP_BITS(nb);
                                        bits_left -= nb;
                                        s          = actbl.look_sym[look];
                                    }
                                    else
                                    {
                                        nb = HUFF_LOOKAHEAD + 1;
                                        if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, actbl, nb)) < 0)
                                        {
                                            return(false);
                                        }
                                        get_buffer = br_state.get_buffer;
                                        bits_left  = br_state.bits_left;
                                    }
                                }
                            }

                            r  = s >> 4;
                            s &= 15;

                            if (s != 0)
                            {
                                k += r;
                                //was CHECK_BIT_BUFFER(br_state, s, return false);
                                if (bits_left < s)
                                {
                                    if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s))
                                    {
                                        return(false);
                                    }
                                    get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                                }
                                //was DROP_BITS(s);
                                bits_left -= s;
                            }
                            else
                            {
                                if (r != 15)
                                {
                                    break;
                                }
                                k += 15;
                            }
                        }
                    }
                }

                // Completed MCU, so update state
                //was BITREAD_SAVE_STATE(cinfo, entropy.bitstate);
                cinfo.src.input_bytes       = br_state.input_bytes;
                cinfo.src.next_input_byte   = br_state.next_input_byte;
                cinfo.src.bytes_in_buffer   = br_state.bytes_in_buffer;
                entropy.bitstate.get_buffer = get_buffer;
                entropy.bitstate.bits_left  = bits_left;

                //was entropy.saved=state;
                state.last_dc_val.CopyTo(entropy.saved.last_dc_val, 0);
            }

            // Account for restart interval (no-op if not using restarts)
            entropy.restarts_to_go--;

            return(true);
        }
Exemplo n.º 20
0
        // Decompress and return some data in the multi-pass case.
        // Always attempts to emit one fully interleaved MCU row ("iMCU" row).
        // Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
        //
        // NB: output_buf contains a plane for each component in image.
        static CONSUME_INPUT decompress_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;

            uint last_iMCU_row = cinfo.total_iMCU_rows - 1;

            // Force some input to be done if we are getting ahead of the input.
            while (cinfo.input_scan_number < cinfo.output_scan_number || (cinfo.input_scan_number == cinfo.output_scan_number && cinfo.input_iMCU_row <= cinfo.output_iMCU_row))
            {
                if (cinfo.inputctl.consume_input(cinfo) == CONSUME_INPUT.JPEG_SUSPENDED)
                {
                    return(CONSUME_INPUT.JPEG_SUSPENDED);
                }
            }

            // 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;
                }

                // Align the buffer for this component.
                short[][][] buffer     = coef.whole_image[ci];
                uint        buffer_ind = cinfo.output_iMCU_row * (uint)compptr.v_samp_factor;

                // Count non-dummy DCT block rows in this iMCU row.
                int block_rows;
                if (cinfo.output_iMCU_row < last_iMCU_row)
                {
                    block_rows = compptr.v_samp_factor;
                }
                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;
                    }
                }
                inverse_DCT_method_ptr inverse_DCT = lossyd.inverse_DCT[ci];
                byte[][] output_ptr     = output_buf[ci];
                uint     output_ptr_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];
                    uint      output_col = 0;
                    for (uint block_num = 0; block_num < compptr.width_in_blocks; block_num++)
                    {
                        inverse_DCT(cinfo, compptr, buffer_ptr[block_num], output_ptr, output_ptr_ind, output_col);
                        output_col += compptr.DCT_scaled_size;
                    }
                    output_ptr_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);
        }
Exemplo n.º 21
0
        // Initialize for a Huffman-compressed scan.
        static void start_pass_phuff_decoder(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec    lossyd  = (jpeg_lossy_d_codec)cinfo.coef;
            phuff_entropy_decoder entropy = (phuff_entropy_decoder)lossyd.entropy_private;

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

            // Validate scan parameters
            bool bad = false;

            if (is_DC_band)
            {
                if (cinfo.Se != 0)
                {
                    bad = true;
                }
            }
            else
            {
                // need not check Ss/Se < 0 since they came from unsigned bytes
                if (cinfo.Ss > cinfo.Se || cinfo.Se >= DCTSIZE2)
                {
                    bad = true;
                }
                // AC scans may have only one component
                if (cinfo.comps_in_scan != 1)
                {
                    bad = true;
                }
            }

            if (cinfo.Ah != 0)
            {
                // Successive approximation refinement scan: must have Al = Ah-1.
                if (cinfo.Al != cinfo.Ah - 1)
                {
                    bad = true;
                }
            }

            // Arguably the maximum Al value should be less than 13 for 8-bit precision,
            // but the spec doesn't say so, and we try to be liberal about what we
            // accept. Note: large Al values could result in out-of-range DC
            // coefficients during early scans, leading to bizarre displays due to
            // overflows in the IDCT math. But we won't crash.
            if (cinfo.Al > 13)
            {
                bad = true;                             // need not check for < 0
            }
            if (bad)
            {
                ERREXIT4(cinfo, J_MESSAGE_CODE.JERR_BAD_PROGRESSION, cinfo.Ss, cinfo.Se, cinfo.Ah, cinfo.Al);
            }

            // Update progression status, and verify that scan order is legal.
            // Note that inter-scan inconsistencies are treated as warnings
            // not fatal errors ... not clear if this is right way to behave.
            for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
            {
                int cindex = cinfo.cur_comp_info[ci].component_index;

                int[] coef_bit_ptr = cinfo.coef_bits[cindex];
                if (!is_DC_band && coef_bit_ptr[0] < 0)
                {
                    WARNMS2(cinfo, J_MESSAGE_CODE.JWRN_BOGUS_PROGRESSION, cindex, 0);                                                // AC without prior DC scan
                }
                for (int coefi = cinfo.Ss; coefi <= cinfo.Se; coefi++)
                {
                    int expected = (coef_bit_ptr[coefi] < 0)?0:coef_bit_ptr[coefi];
                    if (cinfo.Ah != expected)
                    {
                        WARNMS2(cinfo, J_MESSAGE_CODE.JWRN_BOGUS_PROGRESSION, cindex, coefi);
                    }
                    coef_bit_ptr[coefi] = cinfo.Al;
                }
            }

            // Select MCU decoding routine
            if (cinfo.Ah == 0)
            {
                if (is_DC_band)
                {
                    lossyd.entropy_decode_mcu = decode_mcu_DC_first;
                }
                else
                {
                    lossyd.entropy_decode_mcu = decode_mcu_AC_first;
                }
            }
            else
            {
                if (is_DC_band)
                {
                    lossyd.entropy_decode_mcu = decode_mcu_DC_refine;
                }
                else
                {
                    lossyd.entropy_decode_mcu = decode_mcu_AC_refine;
                }
            }

            for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
            {
                jpeg_component_info compptr = cinfo.cur_comp_info[ci];
                // Make sure requested tables are present, and compute derived tables.
                // We may build same derived table more than once, but it's not expensive.
                if (is_DC_band)
                {
                    if (cinfo.Ah == 0)
                    {                     // DC refinement needs no table
                        int tbl = compptr.dc_tbl_no;
                        jpeg_make_d_derived_tbl(cinfo, true, tbl, ref entropy.derived_tbls[tbl]);
                    }
                }
                else
                {
                    int tbl = compptr.ac_tbl_no;
                    jpeg_make_d_derived_tbl(cinfo, false, tbl, ref entropy.derived_tbls[tbl]);

                    // remember the single active table
                    entropy.ac_derived_tbl = entropy.derived_tbls[tbl];
                }
                // Initialize DC predictions to 0
                entropy.saved.last_dc_val[ci] = 0;
            }

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

            // Initialize private state variables
            entropy.saved.EOBRUN = 0;

            // Initialize restart counter
            entropy.restarts_to_go = cinfo.restart_interval;
        }
Exemplo n.º 22
0
        // Huffman MCU decoding.
        // Each of these routines decodes and returns one MCU's worth of
        // Huffman-compressed coefficients.
        // The coefficients are reordered from zigzag order into natural array order,
        // but are not dequantized.
        //
        // The i'th block of the MCU is stored into the block pointed to by
        // MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER.
        //
        // We return false if data source requested suspension. In that case no
        // changes have been made to permanent state. (Exception: some output
        // coefficients may already have been assigned. This is harmless for
        // spectral selection, since we'll just re-assign them on the next call.
        // Successive approximation AC refinement has to be more careful, however.)

        // MCU decoding for DC initial scan (either spectral selection,
        // or first pass of successive approximation).
        static bool decode_mcu_DC_first(jpeg_decompress cinfo, short[][] MCU_data)
        {
            jpeg_lossy_d_codec    lossyd  = (jpeg_lossy_d_codec)cinfo.coef;
            phuff_entropy_decoder entropy = (phuff_entropy_decoder)lossyd.entropy_private;
            int Al = cinfo.Al;

            // Process restart marker if needed; may have to suspend
            if (cinfo.restart_interval != 0)
            {
                if (entropy.restarts_to_go == 0)
                {
                    if (!process_restart_dphuff(cinfo))
                    {
                        return(false);
                    }
                }
            }

            // If we've run out of data, just leave the MCU set to zeroes.
            // This way, we return uniform gray for the remainder of the segment.
            if (!entropy.insufficient_data)
            {
                // Load up working state
                //was BITREAD_STATE_VARS;
                bitread_working_state br_state = new bitread_working_state();

                savable_state state;
                state.last_dc_val = new int[MAX_COMPS_IN_SCAN];

                //was BITREAD_LOAD_STATE(cinfo, entropy.bitstate);
                br_state.cinfo           = cinfo;
                br_state.input_bytes     = cinfo.src.input_bytes;
                br_state.next_input_byte = cinfo.src.next_input_byte;
                br_state.bytes_in_buffer = cinfo.src.bytes_in_buffer;
                ulong get_buffer = entropy.bitstate.get_buffer;
                int   bits_left  = entropy.bitstate.bits_left;

                //was state=entropy.saved;
                state.EOBRUN = entropy.saved.EOBRUN;
                entropy.saved.last_dc_val.CopyTo(state.last_dc_val, 0);

                // Outer loop handles each block in the MCU
                for (int blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++)
                {
                    short[]             block   = MCU_data[blkn];
                    int                 ci      = cinfo.MCU_membership[blkn];
                    jpeg_component_info compptr = cinfo.cur_comp_info[ci];
                    d_derived_tbl       tbl     = entropy.derived_tbls[compptr.dc_tbl_no];

                    int s = 0;

                    // Decode a single block's worth of coefficients

                    // Section F.2.2.1: decode the DC coefficient difference
                    //was HUFF_DECODE(s, br_state, tbl, return false, label1);
                    {
                        int  nb, look;
                        bool label = false;
                        if (bits_left < HUFF_LOOKAHEAD)
                        {
                            if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, 0))
                            {
                                return(false);
                            }
                            get_buffer = br_state.get_buffer;
                            bits_left  = br_state.bits_left;
                            if (bits_left < HUFF_LOOKAHEAD)
                            {
                                nb    = 1;
                                label = true;
                                if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb)) < 0)
                                {
                                    return(false);
                                }
                                get_buffer = br_state.get_buffer;
                                bits_left  = br_state.bits_left;
                            }
                        }

                        if (!label)
                        {
                            //was look=PEEK_BITS(HUFF_LOOKAHEAD);
                            look = ((int)(get_buffer >> (bits_left - HUFF_LOOKAHEAD))) & ((1 << HUFF_LOOKAHEAD) - 1);
                            if ((nb = tbl.look_nbits[look]) != 0)
                            {
                                //was DROP_BITS(nb);
                                bits_left -= nb;
                                s          = tbl.look_sym[look];
                            }
                            else
                            {
                                nb = HUFF_LOOKAHEAD + 1;
                                if ((s = jpeg_huff_decode(ref br_state, get_buffer, bits_left, tbl, nb)) < 0)
                                {
                                    return(false);
                                }
                                get_buffer = br_state.get_buffer;
                                bits_left  = br_state.bits_left;
                            }
                        }
                    }

                    if (s != 0)
                    {
                        //was CHECK_BIT_BUFFER(br_state, s, return false);
                        if (bits_left < s)
                        {
                            if (!jpeg_fill_bit_buffer(ref br_state, get_buffer, bits_left, s))
                            {
                                return(false);
                            }
                            get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
                        }
                        //was r = GET_BITS(s);
                        int r = ((int)(get_buffer >> (bits_left -= s))) & ((1 << s) - 1);
                        //was s=HUFF_EXTEND(r, s);
                        s = (r < (1 << (s - 1))?r + (((-1) << s) + 1):r);
                    }

                    // Convert DC difference to actual value, update last_dc_val
                    s += state.last_dc_val[ci];
                    state.last_dc_val[ci] = s;
                    // Scale and output the coefficient (assumes jpeg_natural_order[0]=0)
                    block[0] = (short)(s << Al);
                }

                // Completed MCU, so update state
                //was BITREAD_SAVE_STATE(cinfo, entropy.bitstate);
                cinfo.src.input_bytes       = br_state.input_bytes;
                cinfo.src.next_input_byte   = br_state.next_input_byte;
                cinfo.src.bytes_in_buffer   = br_state.bytes_in_buffer;
                entropy.bitstate.get_buffer = get_buffer;
                entropy.bitstate.bits_left  = bits_left;

                //was entropy.saved=state;
                entropy.saved.EOBRUN = state.EOBRUN;
                state.last_dc_val.CopyTo(entropy.saved.last_dc_val, 0);
            }

            // Account for restart interval (no-op if not using restarts)
            entropy.restarts_to_go--;

            return(true);
        }
Exemplo n.º 23
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);
        }
Exemplo n.º 24
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);
        }