Пример #1
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;
        }
Пример #2
0
        // Reset within-iMCU-row counters for a new row
        static void start_iMCU_row_c_diff(jpeg_compress cinfo)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;
            c_diff_controller     diff    = (c_diff_controller)losslsc.diff_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)
            {
                diff.MCU_rows_per_iMCU_row = 1;
            }
            else
            {
                if (diff.iMCU_row_num < (cinfo.total_iMCU_rows - 1))
                {
                    diff.MCU_rows_per_iMCU_row = cinfo.cur_comp_info[0].v_samp_factor;
                }
                else
                {
                    diff.MCU_rows_per_iMCU_row = cinfo.cur_comp_info[0].last_row_height;
                }
            }

            diff.mcu_ctr         = 0;
            diff.MCU_vert_offset = 0;
        }
Пример #3
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
            }
        }
Пример #4
0
        // Initialize for a processing pass.
        static void start_pass_ls(jpeg_compress cinfo, J_BUF_MODE pass_mode)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;

            losslsc.scaler_start_pass(cinfo);
            losslsc.predict_start_pass(cinfo);
            losslsc.diff_start_pass(cinfo, pass_mode);
        }
Пример #5
0
        static void simple_downscale(jpeg_compress cinfo, byte[] input_buf, byte[] output_buf, uint width)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;

            for (uint xindex = 0; xindex < width; xindex++)
            {
                output_buf[xindex] = (byte)(input_buf[xindex] >> cinfo.Al);
            }
        }
Пример #6
0
        // Reset predictor at the start of a pass or restart interval.
        static void reset_predictor(jpeg_compress cinfo, int ci)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;
            c_predictor           pred    = (c_predictor)losslsc.pred_private;

            // Initialize restart counter
            pred.restart_rows_to_go[ci] = cinfo.restart_interval / cinfo.MCUs_per_row;

            // Set difference function to first row function
            losslsc.predict_difference[ci] = jpeg_difference_first_row;
        }
Пример #7
0
        // Differencer for the first row in a scan or restart interval. The first
        // sample in the row is differenced using the special predictor constant
        // x=2^(P-Pt-1). The rest of the samples are differenced using the
        // 1-D horizontal predictor (1).
        static void jpeg_difference_first_row(jpeg_compress cinfo, int ci, byte[] input_buf, byte[] prev_row, int[] diff_buf, uint width)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;
            c_predictor           pred    = (c_predictor)losslsc.pred_private;
            bool restart = false;

            int samp = input_buf[0];

            diff_buf[0] = samp - (1 << (cinfo.data_precision - cinfo.Al - 1));

            for (uint xindex = 1; xindex < width; xindex++)
            {
                int Ra = samp;
                samp             = input_buf[xindex];
                diff_buf[xindex] = samp - Ra;
            }

            // Account for restart interval (no-op if not using restarts)
            if (cinfo.restart_interval != 0)
            {
                if (--(pred.restart_rows_to_go[ci]) == 0)
                {
                    reset_predictor(cinfo, ci);
                    restart = true;
                }
            }

            // Now that we have differenced the first row, we want to use the
            // differencer which corresponds to the predictor specified in the
            // scan header.
            //
            // Note that we don't to do this if we have just reset the predictor
            // for a new restart interval.
            if (!restart)
            {
                switch (cinfo.Ss)
                {
                case 1: losslsc.predict_difference[ci] = jpeg_difference1; break;

                case 2: losslsc.predict_difference[ci] = jpeg_difference2; break;

                case 3: losslsc.predict_difference[ci] = jpeg_difference3; break;

                case 4: losslsc.predict_difference[ci] = jpeg_difference4; break;

                case 5: losslsc.predict_difference[ci] = jpeg_difference5; break;

                case 6: losslsc.predict_difference[ci] = jpeg_difference6; break;

                case 7: losslsc.predict_difference[ci] = jpeg_difference7; break;
                }
            }
        }
Пример #8
0
        static void scaler_start_pass(jpeg_compress cinfo)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;

            // Set scaler function based on Pt
            if (cinfo.Al != 0)
            {
                losslsc.scaler_scale = simple_downscale;
            }
            else
            {
                losslsc.scaler_scale = noscale;
            }
        }
Пример #9
0
        // Module initialization routine for the differencer.
        static void jinit_differencer(jpeg_compress cinfo)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;
            c_predictor           pred    = null;

            try
            {
                pred = new c_predictor();
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }
            losslsc.pred_private       = pred;
            losslsc.predict_start_pass = start_pass_c_pred;
        }
Пример #10
0
        // Initialize for an input processing pass.
        static void start_pass_c_pred(jpeg_compress cinfo)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;
            c_predictor           pred    = (c_predictor)losslsc.pred_private;

            // Check that the restart interval is an integer multiple of the number
            // of MCU in an MCU-row.
            if (cinfo.restart_interval % cinfo.MCUs_per_row != 0)
            {
                ERREXIT2(cinfo, J_MESSAGE_CODE.JERR_BAD_RESTART, (int)cinfo.restart_interval, (int)cinfo.MCUs_per_row);
            }

            // Set predictors for start of pass
            for (int ci = 0; ci < cinfo.num_components; ci++)
            {
                reset_predictor(cinfo, ci);
            }
        }
Пример #11
0
        // Process some data in the first pass of a multi-pass case.
        // We process the equivalent of one fully interleaved MCU row ("iMCU" row)
        // per call, ie, v_samp_factor rows for each component in the image.
        // This amount of data is read from the source buffer and saved into the arrays.
        //
        // We must also emit the data to the compressor. This is conveniently
        // done by calling compress_output_diff() after we've loaded the current strip
        // of the arrays.
        //
        // NB: input_buf contains a plane for each component in image. All components
        // are loaded into the arrays in this pass. However, it may be that
        // only a subset of the components are emitted to the compressor during
        // this first pass; be careful about looking at the scan-dependent variables
        // (MCU dimensions, etc).
        static bool compress_first_pass_diff(jpeg_compress cinfo, byte[][][] input_buf)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;
            c_diff_controller     diff    = (c_diff_controller)losslsc.diff_private;

            uint last_iMCU_row = cinfo.total_iMCU_rows - 1;

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

                // Count non-dummy sample rows in this iMCU row.
                int samp_rows;
                if (diff.iMCU_row_num < last_iMCU_row)
                {
                    samp_rows = compptr.v_samp_factor;
                }
                else
                {
                    // NB: can't use last_row_height here, since may not be set!
                    samp_rows = (int)(compptr.height_in_blocks % compptr.v_samp_factor);
                    if (samp_rows == 0)
                    {
                        samp_rows = compptr.v_samp_factor;
                    }
                }

                uint samps_across = compptr.width_in_blocks;

                // Perform point transform scaling and prediction/differencing for all
                // non-dummy rows in this iMCU row. Each call on these functions
                // process a complete row of samples.
                for (int samp_row = 0; samp_row < samp_rows; samp_row++)
                {
                    Array.Copy(input_buf[ci][samp_row], diff.whole_image[ci][samp_row + diff.iMCU_row_num * compptr.v_samp_factor], samps_across);
                }
            }

            // NB: compress_output will increment iMCU_row_num if successful.
            // A suspension return will result in redoing all the work above next time.

            // Emit data to the compressor, sharing code with subsequent passes
            return(compress_output_diff(cinfo, input_buf));
        }
Пример #12
0
		// Initialize the lossless compression codec.
		// This is called only once, during master selection.
		static void jinit_lossless_c_codec(jpeg_compress cinfo)
		{
			jpeg_lossless_c_codec losslsc=null;

			// Create subobject in permanent pool
			try
			{
				losslsc=new jpeg_lossless_c_codec();
			}
			catch
			{
				ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
			}
			cinfo.coef=losslsc;

			// Initialize sub-modules

			// Scaler
			jinit_c_scaler(cinfo);

			// Differencer
			jinit_differencer(cinfo);

			// Entropy encoding: either Huffman or arithmetic coding.
			if(cinfo.arith_code)
			{
				ERREXIT(cinfo, J_MESSAGE_CODE.JERR_ARITH_NOTIMPL);
			}
			else
			{
				jinit_lhuff_encoder(cinfo);
			}

			// Need a full-image difference buffer in any multi-pass mode.
			jinit_c_diff_controller(cinfo, (bool)(cinfo.num_scans>1|| cinfo.optimize_coding));

			// Initialize method pointers.
			//
			// Note: entropy_start_pass and entropy_finish_pass are assigned in
			// jclhuff.cs and compress_data is assigned in jcdiffct.cs.
			losslsc.start_pass=start_pass_ls;
		}
Пример #13
0
        // Initialize the lossless compression codec.
        // This is called only once, during master selection.
        static void jinit_lossless_c_codec(jpeg_compress cinfo)
        {
            jpeg_lossless_c_codec losslsc = null;

            // Create subobject in permanent pool
            try
            {
                losslsc = new jpeg_lossless_c_codec();
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }
            cinfo.coef = losslsc;

            // Initialize sub-modules

            // Scaler
            jinit_c_scaler(cinfo);

            // Differencer
            jinit_differencer(cinfo);

            // Entropy encoding: either Huffman or arithmetic coding.
            if (cinfo.arith_code)
            {
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_ARITH_NOTIMPL);
            }
            else
            {
                jinit_lhuff_encoder(cinfo);
            }

            // Need a full-image difference buffer in any multi-pass mode.
            jinit_c_diff_controller(cinfo, (bool)(cinfo.num_scans > 1 || cinfo.optimize_coding));

            // Initialize method pointers.
            //
            // Note: entropy_start_pass and entropy_finish_pass are assigned in
            // jclhuff.cs and compress_data is assigned in jcdiffct.cs.
            losslsc.start_pass = start_pass_ls;
        }
Пример #14
0
        // Process some data in subsequent passes of a multi-pass case.
        // We process the equivalent of one fully interleaved MCU row ("iMCU" row)
        // per call, ie, v_samp_factor rows for each component in the scan.
        // The data is obtained from the arrays and fed to the compressor.
        // Returns true if the iMCU row is completed, false if suspended.
        //
        // NB: input_buf is ignored; it is likely to be a null pointer.
        static bool compress_output_diff(jpeg_compress cinfo, byte[][][] input_buf)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;
            c_diff_controller     diff    = (c_diff_controller)losslsc.diff_private;

            byte[][][] buffer     = new byte[MAX_COMPONENTS][][];
            int[]      buffer_ind = new int[MAX_COMPONENTS];

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

            return(compress_data_diff(cinfo, buffer, buffer_ind));
        }
Пример #15
0
        // Initialize for a processing pass.
        static void start_pass_diff(jpeg_compress cinfo, J_BUF_MODE pass_mode)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;
            c_diff_controller     diff    = (c_diff_controller)losslsc.diff_private;

            diff.iMCU_row_num = 0;
            start_iMCU_row_c_diff(cinfo);

            switch (pass_mode)
            {
            case J_BUF_MODE.JBUF_PASS_THRU:
                if (diff.whole_image[0] != null)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
                }
                losslsc.compress_data = compress_data_diff;
                break;

#if FULL_SAMP_BUFFER_SUPPORTED
            case J_BUF_MODE.JBUF_SAVE_AND_PASS:
                if (diff.whole_image[0] == null)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
                }
                losslsc.compress_data = compress_first_pass_diff;
                break;

            case J_BUF_MODE.JBUF_CRANK_DEST:
                if (diff.whole_image[0] == null)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
                }
                losslsc.compress_data = compress_output_diff;
                break;
#endif
            default:
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
                break;
            }
        }
Пример #16
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;
                }
            }
        }
Пример #17
0
        static void jinit_c_scaler(jpeg_compress cinfo)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;

            losslsc.scaler_start_pass = scaler_start_pass;
        }
Пример #18
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;
        }
Пример #19
0
        // Initialize difference buffer controller.
        static void jinit_c_diff_controller(jpeg_compress cinfo, bool need_full_buffer)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;
            c_diff_controller     diff    = null;

            try
            {
                diff = new c_diff_controller();
            }
            catch
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
            }
            losslsc.diff_private    = diff;
            losslsc.diff_start_pass = start_pass_diff;

            // Create the prediction row buffers.
            for (int ci = 0; ci < cinfo.num_components; ci++)
            {
                jpeg_component_info compptr = cinfo.comp_info[ci];
                try
                {
                    diff.cur_row[ci]  = new byte[jround_up(compptr.width_in_blocks, compptr.h_samp_factor)];
                    diff.prev_row[ci] = new byte[jround_up(compptr.width_in_blocks, compptr.h_samp_factor)];
                }
                catch
                {
                    ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
                }
            }

            // Create the difference buffer.
            for (int ci = 0; ci < cinfo.num_components; ci++)
            {
                jpeg_component_info compptr = cinfo.comp_info[ci];
                diff.diff_buf[ci] = alloc_darray(cinfo, (uint)jround_up(compptr.width_in_blocks, compptr.h_samp_factor), (uint)compptr.v_samp_factor);

                // Prefill difference rows with zeros. We do this because only actual
                // data is placed in the buffers during prediction/differencing, leaving
                // any dummy differences at the right edge as zeros, which will encode
                // to the smallest amount of data.
                for (int row = 0; row < compptr.v_samp_factor; row++)
                {
                    int c = (int)jround_up(compptr.width_in_blocks, compptr.h_samp_factor);
                    for (int i = 0; i < c; i++)
                    {
                        diff.diff_buf[ci][row][i] = 0;
                    }
                }
            }

            // Create the sample buffer.
            if (need_full_buffer)
            {
#if FULL_SAMP_BUFFER_SUPPORTED
                // Allocate a full-image array for each component,
                // padded to a multiple of samp_factor differences in each direction.
                for (int ci = 0; ci < cinfo.num_components; ci++)
                {
                    jpeg_component_info compptr = cinfo.comp_info[ci];
                    diff.whole_image[ci] = alloc_sarray(cinfo, (uint)jround_up(compptr.width_in_blocks, compptr.h_samp_factor), (uint)jround_up(compptr.height_in_blocks, compptr.v_samp_factor));
                }
#else
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
#endif
            }
            else
            {
                diff.whole_image[0] = null;            // flag for no arrays
            }
        }
Пример #20
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);
        }
Пример #21
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);
        }
Пример #22
0
        // Special version of compress_data_diff with input_buf offsets.
        static bool compress_data_diff(jpeg_compress cinfo, byte[][][] input_buf, int[] input_buf_ind)
        {
            jpeg_lossless_c_codec losslsc = (jpeg_lossless_c_codec)cinfo.coef;
            c_diff_controller     diff    = (c_diff_controller)losslsc.diff_private;

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

            // Loop to write as much as one whole iMCU row
            for (int yoffset = diff.MCU_vert_offset; yoffset < diff.MCU_rows_per_iMCU_row; yoffset++)
            {
                uint MCU_col_num = diff.mcu_ctr;               // index of current MCU within row

                // Scale and predict each scanline of the MCU-row separately.
                //
                // Note: We only do this if we are at the start of a MCU-row, ie,
                // we don't want to reprocess a row suspended by the output.
                if (MCU_col_num == 0)
                {
                    for (int comp = 0; comp < cinfo.comps_in_scan; comp++)
                    {
                        jpeg_component_info compptr = cinfo.cur_comp_info[comp];
                        int ci = compptr.component_index;
                        int samp_rows;
                        if (diff.iMCU_row_num < last_iMCU_row)
                        {
                            samp_rows = compptr.v_samp_factor;
                        }
                        else
                        {
                            // NB: can't use last_row_height here, since may not be set!
                            samp_rows = (int)(compptr.height_in_blocks % compptr.v_samp_factor);
                            if (samp_rows == 0)
                            {
                                samp_rows = compptr.v_samp_factor;
                            }
                            else
                            {
                                // Fill dummy difference rows at the bottom edge with zeros, which
                                // will encode to the smallest amount of data.
                                for (int samp_row = samp_rows; samp_row < compptr.v_samp_factor; samp_row++)
                                {
                                    int c = jround_up((int)compptr.width_in_blocks, (int)compptr.h_samp_factor);
                                    for (int i = 0; i < c; i++)
                                    {
                                        diff.diff_buf[ci][samp_row][i] = 0;
                                    }
                                }
                            }
                        }

                        uint samps_across = compptr.width_in_blocks;
                        for (int samp_row = 0; samp_row < samp_rows; samp_row++)
                        {
                            losslsc.scaler_scale(cinfo, input_buf[ci][input_buf_ind[ci] + samp_row], diff.cur_row[ci], samps_across);
                            losslsc.predict_difference[ci](cinfo, ci, diff.cur_row[ci], diff.prev_row[ci], diff.diff_buf[ci][samp_row], samps_across);

                            byte[] temp = diff.cur_row[ci];
                            diff.cur_row[ci]  = diff.prev_row[ci];
                            diff.prev_row[ci] = temp;
                        }
                    }
                }

                // Try to write the MCU-row (or remaining portion of suspended MCU-row).
                uint MCU_count = losslsc.entropy_encode_mcus(cinfo, diff.diff_buf, (uint)yoffset, MCU_col_num, cinfo.MCUs_per_row - MCU_col_num);
                if (MCU_count != cinfo.MCUs_per_row - MCU_col_num)
                {
                    // Suspension forced; update state counters and exit
                    diff.MCU_vert_offset = yoffset;
                    diff.mcu_ctr        += MCU_col_num;
                    return(false);
                }

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

            // Completed the iMCU row, advance counters for next one
            diff.iMCU_row_num++;
            start_iMCU_row_c_diff(cinfo);
            return(true);
        }