예제 #1
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;
        }
예제 #2
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));
        }
예제 #3
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));
        }
예제 #4
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;
            }
        }
예제 #5
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
		}
예제 #6
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
            }
        }
예제 #7
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);
        }