Example #1
0
        // Module initialization routine for Huffman entropy encoding.
        static void jinit_lhuff_encoder(jpeg_compress cinfo)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;
            lhuff_entropy_encoder entropy = null;

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

            losslsc.entropy_private        = entropy;
            losslsc.entropy_start_pass     = start_pass_huff_ls;
            losslsc.need_optimization_pass = need_optimization_pass_ls;

            // Mark tables unallocated
            for (int i = 0; i < NUM_HUFF_TBLS; i++)
            {
                entropy.derived_tbls[i] = null;
#if ENTROPY_OPT_SUPPORTED
                entropy.count_ptrs[i] = null;
#endif
            }
        }
Example #2
0
        // Finish up at the end of a Huffman-compressed scan.
        static void finish_pass_huff_ls(jpeg_compress cinfo)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;
            lhuff_entropy_encoder entropy = (lhuff_entropy_encoder)losslsc.entropy_private;

            // Load up working state ... flush_bits needs it
            working_state_ls state;

            state.output_bytes     = cinfo.dest.output_bytes;
            state.next_output_byte = cinfo.dest.next_output_byte;
            state.free_in_buffer   = cinfo.dest.free_in_buffer;
            state.cur   = entropy.saved;
            state.cinfo = cinfo;

            // Flush out the last data
            if (!flush_bits(ref state))
            {
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CANT_SUSPEND);
            }

            // Update state
            cinfo.dest.output_bytes     = state.output_bytes;
            cinfo.dest.next_output_byte = state.next_output_byte;
            cinfo.dest.free_in_buffer   = state.free_in_buffer;
            entropy.saved = state.cur;
        }
Example #3
0
        // Finish up a statistics-gathering pass and create the new Huffman tables.
        static void finish_pass_gather_ls(jpeg_compress cinfo)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;
            lhuff_entropy_encoder entropy = (lhuff_entropy_encoder)losslsc.entropy_private;

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

            for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
            {
                jpeg_component_info compptr = cinfo.cur_comp_info[ci];
                int dctbl = compptr.dc_tbl_no;
                if (!did_dc[dctbl])
                {
                    if (cinfo.dc_huff_tbl_ptrs[dctbl] == null)
                    {
                        cinfo.dc_huff_tbl_ptrs[dctbl] = jpeg_alloc_huff_table(cinfo);
                    }
                    jpeg_gen_optimal_table(cinfo, cinfo.dc_huff_tbl_ptrs[dctbl], entropy.count_ptrs[dctbl]);
                    did_dc[dctbl] = true;
                }
            }
        }
Example #4
0
        // Initialize for a Huffman-compressed scan.
        // If gather_statistics is true, we do not output anything during the scan,
        // just count the Huffman symbols used and generate Huffman code tables.
        static void start_pass_huff_ls(jpeg_compress cinfo, bool gather_statistics)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;
            lhuff_entropy_encoder entropy = (lhuff_entropy_encoder)losslsc.entropy_private;

            if (gather_statistics)
            {
#if ENTROPY_OPT_SUPPORTED
                losslsc.entropy_encode_mcus = encode_mcus_gather_ls;
                losslsc.entropy_finish_pass = finish_pass_gather_ls;
#else
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED);
#endif
            }
            else
            {
                losslsc.entropy_encode_mcus = encode_mcus_huff_ls;
                losslsc.entropy_finish_pass = finish_pass_huff_ls;
            }

            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;
                if (gather_statistics)
                {
#if ENTROPY_OPT_SUPPORTED
                    // Check for invalid table indexes
                    // (make_c_derived_tbl does this in the other path)
                    if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS)
                    {
                        ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_NO_HUFF_TABLE, dctbl);
                    }

                    // Allocate and zero the statistics tables
                    // Note that jpeg_gen_optimal_table expects 257 entries in each table!
                    if (entropy.count_ptrs[dctbl] == null)
                    {
                        entropy.count_ptrs[dctbl] = new int[257];
                    }
                    else
                    {
                        for (int i = 0; i < 257; i++)
                        {
                            entropy.count_ptrs[dctbl][i] = 0;
                        }
                    }
#endif
                }
                else
                {
                    // Compute derived values for Huffman tables
                    // We may do this more than once for a table, but it's not expensive
                    jpeg_make_c_derived_tbl(cinfo, true, dctbl, ref entropy.derived_tbls[dctbl]);
                }
            }

            // Precalculate encoding info for each sample in an MCU of this scan
            int ptrn = 0;
            for (int sampn = 0; sampn < cinfo.block_in_MCU;)
            {
                jpeg_component_info compptr = cinfo.cur_comp_info[cinfo.MCU_membership[sampn]];
                int ci = compptr.component_index;
                //ci=cinfo.MCU_membership[sampn];
                //compptr=cinfo.cur_comp_info[ci];
                for (int yoffset = 0; yoffset < compptr.MCU_height; yoffset++, ptrn++)
                {
                    // Precalculate the setup info for each input pointer
                    entropy.input_ptr_info[ptrn].ci        = ci;
                    entropy.input_ptr_info[ptrn].yoffset   = yoffset;
                    entropy.input_ptr_info[ptrn].MCU_width = compptr.MCU_width;
                    for (int xoffset = 0; xoffset < compptr.MCU_width; xoffset++, sampn++)
                    {
                        // Precalculate the input pointer index for each sample
                        entropy.input_ptr_index[sampn] = ptrn;
                        // Precalculate which tables to use for each sample
                        entropy.cur_tbls[sampn]   = entropy.derived_tbls[compptr.dc_tbl_no];
                        entropy.cur_counts[sampn] = entropy.count_ptrs[compptr.dc_tbl_no];
                    }
                }
            }
            entropy.num_input_ptrs = ptrn;

            // Initialize bit buffer to empty
            entropy.saved.put_buffer = 0;
            entropy.saved.put_bits   = 0;

            // Initialize restart stuff
            entropy.restarts_to_go   = cinfo.restart_interval;
            entropy.next_restart_num = 0;
        }
Example #5
0
        // Huffman coding optimization.
        //
        // We first scan the supplied data and count the number of uses of each symbol
        // that is to be Huffman-coded. (This process MUST agree with the code above.)
        // Then we build a Huffman coding tree for the observed counts.
        // Symbols which are not needed at all for the particular image are not
        // assigned any code, which saves space in the DHT marker as well as in
        // the compressed data.
#if ENTROPY_OPT_SUPPORTED
        // Trial-encode one nMCU's worth of Huffman-compressed differences.
        // No data is actually output, so no suspension return is possible.
        static uint encode_mcus_gather_ls(jpeg_compress cinfo, int[][][] diff_buf, uint MCU_row_num, uint MCU_col_num, uint nMCU)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;
            lhuff_entropy_encoder entropy = (lhuff_entropy_encoder)losslsc.entropy_private;

            // Take care of restart intervals if needed
            if (cinfo.restart_interval != 0)
            {
                if (entropy.restarts_to_go == 0)
                {
                    entropy.restarts_to_go = cinfo.restart_interval;                                         // Update restart state
                }
                entropy.restarts_to_go--;
            }

            // Set input pointer locations based on MCU_col_num
            for (int ptrn = 0; ptrn < entropy.num_input_ptrs; ptrn++)
            {
                int ci        = entropy.input_ptr_info[ptrn].ci;
                int yoffset   = entropy.input_ptr_info[ptrn].yoffset;
                int MCU_width = entropy.input_ptr_info[ptrn].MCU_width;
                entropy.input_ptr[ptrn]     = diff_buf[ci][MCU_row_num + yoffset];
                entropy.input_ptr_ind[ptrn] = (int)MCU_col_num * MCU_width;
            }

            for (uint mcu_num = 0; mcu_num < nMCU; mcu_num++)
            {
                // Inner loop handles the samples in the MCU
                for (int sampn = 0; sampn < cinfo.block_in_MCU; sampn++)
                {
                    c_derived_tbl dctbl  = entropy.cur_tbls[sampn];
                    int[]         counts = entropy.cur_counts[sampn];

                    // Encode the difference per section H.1.2.2

                    // Input the sample difference
                    int temp3 = entropy.input_ptr_index[sampn];
                    int temp  = entropy.input_ptr[temp3][entropy.input_ptr_ind[temp3]++];

                    if ((temp & 0x8000) != 0)
                    {                            // instead of temp < 0
                        temp = (-temp) & 0x7FFF; // absolute value, mod 2^16
                        if (temp == 0)
                        {
                            temp = 0x8000;                                      // special case: magnitude = 32768
                        }
                    }
                    else
                    {
                        temp &= 0x7FFF;                                                 // abs value mod 2^16
                    }
                    // Find the number of bits needed for the magnitude of the difference
                    int nbits = 0;
                    while (temp != 0)
                    {
                        nbits++;
                        temp >>= 1;
                    }

                    // Check for out-of-range difference values.
                    if (nbits > MAX_DIFF_BITS)
                    {
                        ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_DIFF);
                    }

                    // Count the Huffman symbol for the number of bits
                    counts[nbits]++;
                }
            }

            return(nMCU);
        }
Example #6
0
        // Encode and output one nMCU's worth of Huffman-compressed differences.
        static uint encode_mcus_huff_ls(jpeg_compress cinfo, int[][][] diff_buf, uint MCU_row_num, uint MCU_col_num, uint nMCU)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;
            lhuff_entropy_encoder entropy = (lhuff_entropy_encoder)losslsc.entropy_private;

            // Load up working state
            working_state_ls state;

            state.output_bytes     = cinfo.dest.output_bytes;
            state.next_output_byte = cinfo.dest.next_output_byte;
            state.free_in_buffer   = cinfo.dest.free_in_buffer;
            state.cur   = entropy.saved;
            state.cinfo = cinfo;

            // Emit restart marker if needed
            if (cinfo.restart_interval != 0)
            {
                if (entropy.restarts_to_go == 0)
                {
                    if (!emit_restart(ref state, entropy.next_restart_num))
                    {
                        return(0);
                    }
                }
            }

            // Set input pointer locations based on MCU_col_num
            for (int ptrn = 0; ptrn < entropy.num_input_ptrs; ptrn++)
            {
                int ci        = entropy.input_ptr_info[ptrn].ci;
                int yoffset   = entropy.input_ptr_info[ptrn].yoffset;
                int MCU_width = entropy.input_ptr_info[ptrn].MCU_width;
                entropy.input_ptr[ptrn]     = diff_buf[ci][MCU_row_num + yoffset];
                entropy.input_ptr_ind[ptrn] = (int)MCU_col_num * MCU_width;
            }

            for (uint mcu_num = 0; mcu_num < nMCU; mcu_num++)
            {
                // Inner loop handles the samples in the MCU
                for (int sampn = 0; sampn < cinfo.block_in_MCU; sampn++)
                {
                    c_derived_tbl dctbl = entropy.cur_tbls[sampn];

                    // Encode the difference per section H.1.2.2

                    // Input the sample difference
                    int temp3 = entropy.input_ptr_index[sampn];
                    int temp  = entropy.input_ptr[temp3][entropy.input_ptr_ind[temp3]++];

                    int temp2;
                    if ((temp & 0x8000) != 0)
                    {                            // instead of temp < 0
                        temp = (-temp) & 0x7FFF; // absolute value, mod 2^16
                        if (temp == 0)
                        {
                            temp2 = temp = 0x8000;                              // special case: magnitude = 32768
                        }
                        temp2 = ~temp;                                          // one's complement of magnitude
                    }
                    else
                    {
                        temp &= 0x7FFF;                         // abs value mod 2^16
                        temp2 = temp;                           // magnitude
                    }

                    // Find the number of bits needed for the magnitude of the difference
                    int nbits = 0;
                    while (temp != 0)
                    {
                        nbits++;
                        temp >>= 1;
                    }

                    // Check for out-of-range difference values.
                    if (nbits > MAX_DIFF_BITS)
                    {
                        ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_DIFF);
                    }

                    // Emit the Huffman-coded symbol for the number of bits
                    if (!emit_bits(ref state, dctbl.ehufco[nbits], dctbl.ehufsi[nbits]))
                    {
                        return(mcu_num);
                    }

                    // Emit that number of bits of the value, if positive,
                    // or the complement of its magnitude, if negative.
                    if (nbits != 0 &&                           // emit_bits rejects calls with size 0
                        nbits != 16)                            // special case: no bits should be emitted
                    {
                        if (!emit_bits(ref state, (uint)temp2, nbits))
                        {
                            return(mcu_num);
                        }
                    }
                }

                // Completed MCU, so update state
                cinfo.dest.output_bytes     = state.output_bytes;
                cinfo.dest.next_output_byte = state.next_output_byte;
                cinfo.dest.free_in_buffer   = state.free_in_buffer;
                entropy.saved = state.cur;

                // Update restart-interval state too
                if (cinfo.restart_interval != 0)
                {
                    if (entropy.restarts_to_go == 0)
                    {
                        entropy.restarts_to_go = cinfo.restart_interval;
                        entropy.next_restart_num++;
                        entropy.next_restart_num &= 7;
                    }
                    entropy.restarts_to_go--;
                }
            }

            return(nMCU);
        }
Example #7
0
		// Module initialization routine for Huffman entropy encoding.
		static void jinit_lhuff_encoder(jpeg_compress cinfo)
		{
			jpeg_lossless_c_codec losslsc=(jpeg_lossless_c_codec)cinfo.coef;
			lhuff_entropy_encoder entropy=null;

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

			losslsc.entropy_private=entropy;
			losslsc.entropy_start_pass=start_pass_huff_ls;
			losslsc.need_optimization_pass=need_optimization_pass_ls;

			// Mark tables unallocated
			for(int i=0; i<NUM_HUFF_TBLS; i++)
			{
				entropy.derived_tbls[i]=null;
#if ENTROPY_OPT_SUPPORTED
				entropy.count_ptrs[i]=null;
#endif
			}
		}