Example #1
0
		// Initialize for a processing pass.
		static void start_pass_coef(jpeg_compress cinfo, J_BUF_MODE pass_mode)
		{
			jpeg_lossy_c_codec lossyc=(jpeg_lossy_c_codec)cinfo.coef;
			c_coef_controller coef=(c_coef_controller)lossyc.coef_private;

			coef.iMCU_row_num=0;
			start_iMCU_row_c_coef(cinfo);

			switch(pass_mode)
			{
				case J_BUF_MODE.JBUF_PASS_THRU:
					if(coef.whole_image[0]!=null) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
					lossyc.compress_data=compress_data_coef;
					break;
#if FULL_COEF_BUFFER_SUPPORTED
				case J_BUF_MODE.JBUF_SAVE_AND_PASS:
					if(coef.whole_image[0]==null) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
					lossyc.compress_data=compress_first_pass_coef;
					break;
				case J_BUF_MODE.JBUF_CRANK_DEST:
					if(coef.whole_image[0]==null) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
					lossyc.compress_data=compress_output_coef;
					break;
#endif
				default:
					ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
					break;
			}
		}
Example #2
0
		// Master selection of compression modules.
		// This is done once at the start of processing an image. We determine
		// which modules will be used and give them appropriate initialization calls.
		static void jinit_compress_master(jpeg_compress cinfo)
		{
			// Initialize master control (includes parameter checking/processing)
			jinit_c_master_control(cinfo, false); // full compression

			// Initialize compression codec
			jinit_c_codec(cinfo);

			// Preprocessing
			if(!cinfo.raw_data_in)
			{
				jinit_color_converter(cinfo);
				jinit_downsampler(cinfo);
				jinit_c_prep_controller(cinfo, false); // never need full buffer here
			}

			jinit_c_main_controller(cinfo, false); // never need full buffer here

			jinit_marker_writer(cinfo);

			// Write the datastream header (SOI) immediately.
			// Frame and scan headers are postponed till later.
			// This lets application insert special markers after the SOI.
			cinfo.marker.write_file_header(cinfo);
		}
Example #3
0
		// Initialize for RGB->YCC colorspace conversion.
		static void rgb_ycc_start(jpeg_compress cinfo)
		{
			my_color_converter cconvert=(my_color_converter)cinfo.cconvert;
			int[] rgb_ycc_tab=null;
			try
			{
				// Allocate and fill in the conversion tables.
				cconvert.rgb_ycc_tab=rgb_ycc_tab=new int[TABLE_SIZE];
			}
			catch
			{
				ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
			}
			for(int i=0; i<=MAXJSAMPLE; i++)
			{
				rgb_ycc_tab[i+R_Y_OFF]=FIX_029900*i;
				rgb_ycc_tab[i+G_Y_OFF]=FIX_058700*i;
				rgb_ycc_tab[i+B_Y_OFF]=FIX_011400*i+ONE_HALF;
				rgb_ycc_tab[i+R_CB_OFF]=(-FIX_016874)*i;
				rgb_ycc_tab[i+G_CB_OFF]=(-FIX_033126)*i;
				// We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
				// This ensures that the maximum output will round to MAXJSAMPLE
				// not MAXJSAMPLE+1, and thus that we don't have to range-limit.
				rgb_ycc_tab[i+B_CB_OFF]=FIX_050000*i+CBCR_OFFSET+ONE_HALF-1;
				// B=>Cb and R=>Cr tables are the same
				// rgb_ycc_tab[i+R_CR_OFF]=FIX_050000*i+CBCR_OFFSET+ONE_HALF-1;
				rgb_ycc_tab[i+G_CR_OFF]=(-FIX_041869)*i;
				rgb_ycc_tab[i+B_CR_OFF]=(-FIX_008131)*i;
			}
		}
Example #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);
		}
Example #5
0
		// Initialize the compression codec.
		// This is called only once, during master selection.
		static void jinit_c_codec(jpeg_compress cinfo)
		{
			if(cinfo.process==J_CODEC_PROCESS.JPROC_LOSSLESS)
			{
#if C_LOSSLESS_SUPPORTED
				jinit_lossless_c_codec(cinfo);
#else
				ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED);
#endif
			}
			else jinit_lossy_c_codec(cinfo);
		}
Example #6
0
        // Finish JPEG compression.
        //
        // If a multipass operating mode was selected, this may do a great deal of
        // work including most of the actual output.
        public static void jpeg_finish_compress(jpeg_compress cinfo)
        {
            if (cinfo.global_state == STATE.CSCANNING || cinfo.global_state == STATE.CRAW_OK)
            {
                // Terminate first pass
                if (cinfo.next_scanline < cinfo.image_height)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_TOO_LITTLE_DATA);
                }
                cinfo.master.finish_pass(cinfo);
            }
            else if (cinfo.global_state != STATE.CWRCOEFS)
            {
                ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_BAD_STATE, cinfo.global_state);
            }

            // Perform any remaining passes
            while (!cinfo.master.is_last_pass)
            {
                cinfo.master.prepare_for_pass(cinfo);
                for (uint iMCU_row = 0; iMCU_row < cinfo.total_iMCU_rows; iMCU_row++)
                {
                    if (cinfo.progress != null)
                    {
                        cinfo.progress.pass_counter = (int)iMCU_row;
                        cinfo.progress.pass_limit   = (int)cinfo.total_iMCU_rows;
                        cinfo.progress.progress_monitor(cinfo);
                    }
                    // We bypass the main controller and invoke coef controller directly;
                    // all work is being done from the coefficient buffer.
                    if (!cinfo.coef.compress_data(cinfo, null))
                    {
                        ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CANT_SUSPEND);
                    }
                }
                cinfo.master.finish_pass(cinfo);
            }

            // Write EOI, do final cleanup
            cinfo.marker.write_file_trailer(cinfo);
            cinfo.dest.term_destination(cinfo);

            // We can use jpeg_abort to release memory and reset global_state
            jpeg_abort(cinfo);
        }
Example #7
0
		// Initialize for a processing pass.
		static void start_pass_c_main(jpeg_compress cinfo, J_BUF_MODE pass_mode)
		{
			my_c_main_controller main=(my_c_main_controller)cinfo.main;

			// Do nothing in raw-data mode.
			if(cinfo.raw_data_in) return;

			main.cur_iMCU_row=0;		// initialize counters
			main.rowgroup_ctr=0;
			main.suspended=false;
			main.pass_mode=pass_mode;	// save mode for use by process_data

			switch(pass_mode)
			{
				case J_BUF_MODE.JBUF_PASS_THRU: main.process_data=process_data_simple_c_main; break;
				default: ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE); break;
			}
		}
Example #8
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);
            }
        }
Example #9
0
		// Process some data.
		// This	routine handles the simple pass-through mode,
		// where we have only a strip buffer.
		static void process_data_simple_c_main(jpeg_compress cinfo, byte[][] input_buf, ref uint in_row_ctr, uint in_rows_avail)
		{
			my_c_main_controller main=(my_c_main_controller)cinfo.main;
			uint DCT_size=cinfo.DCT_size;

			while(main.cur_iMCU_row<cinfo.total_iMCU_rows)
			{
				// Read input data if we haven't filled the main buffer yet
				if(main.rowgroup_ctr<DCT_size)
					cinfo.prep.pre_process_data(cinfo, input_buf, ref in_row_ctr, in_rows_avail, main.buffer, ref main.rowgroup_ctr, (uint)DCT_size);

				// If we don't have a full iMCU row buffered, return to application for
				// more data. Note that preprocessor will always pad to fill the iMCU row
				// at the bottom of the image.
				if(main.rowgroup_ctr!=DCT_size) return;

				// Send the completed row to the compressor
				if(!cinfo.coef.compress_data(cinfo, main.buffer))
				{
					// If compressor did not consume the whole row, then we must need to
					// suspend processing and return to the application. In this situation
					// we pretend we didn't yet consume the last input row; otherwise, if
					// it happened to be the last row of the image, the application would
					// think we were done.
					if(!main.suspended)
					{
						in_row_ctr--;
						main.suspended=true;
					}
					return;
				}

				// We did finish the row. Undo our little suspension hack if a previous
				// call suspended; then mark the main buffer empty.
				if(main.suspended)
				{
					in_row_ctr++;
					main.suspended=false;
				}
				main.rowgroup_ctr=0;
				main.cur_iMCU_row++;
			} // while(...)
		}
Example #10
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;
        }
Example #11
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;
		}
Example #12
0
        // Emit a restart marker & resynchronize predictions.
        static void emit_restart_arith(jpeg_compress cinfo, int restart_num)
        {
            arith_entropy_encoder entropy = (arith_entropy_encoder)cinfo.coef;

            finish_pass_c_arith(cinfo);

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

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

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

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

            // Reset arithmetic encoding variables
            entropy.c      = 0;
            entropy.a      = 0x10000;
            entropy.sc     = 0;
            entropy.zc     = 0;
            entropy.ct     = 11;
            entropy.buffer = -1;                // empty
        }
Example #13
0
		// Reset within-iMCU-row counters for a new row
		static void start_iMCU_row_c_coef(jpeg_compress cinfo)
		{
			jpeg_lossy_c_codec lossyc=(jpeg_lossy_c_codec)cinfo.coef;
			c_coef_controller coef=(c_coef_controller)lossyc.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(coef.iMCU_row_num<(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;
		}
Example #14
0
		// Write an abbreviated table-specification datastream.
		// This consists of SOI, DQT and DHT tables, and EOI.
		// Any table that is defined and not marked sent_table = true will be
		// emitted. Note that all tables will be marked sent_table = true at exit.
		static void write_tables_only(jpeg_compress cinfo)
		{
			emit_marker(cinfo, JPEG_MARKER.M_SOI);

			for(int i=0; i<NUM_QUANT_TBLS; i++)
			{
				if(cinfo.quant_tbl_ptrs[i]!=null) emit_dqt(cinfo, i);
			}

			if(!cinfo.arith_code)
			{
				for(int i=0; i<NUM_HUFF_TBLS; i++)
				{
					if(cinfo.dc_huff_tbl_ptrs[i]!=null) emit_dht(cinfo, i, false);
					if(cinfo.ac_huff_tbl_ptrs[i]!=null) emit_dht(cinfo, i, true);
				}
			}

			emit_marker(cinfo, JPEG_MARKER.M_EOI);
		}
Example #15
0
        // Convert some rows of samples to the JPEG colorspace.
        // This version handles multi-component colorspaces without conversion.
        // We assume input_components == num_components.
        static void null_convert(jpeg_compress cinfo, byte[][] input_buf, uint in_row_index, byte[][][] output_buf, uint output_row, int num_rows)
        {
            int  nc       = cinfo.num_components;
            uint num_cols = cinfo.image_width;

            for (uint input_row = 0; input_row < num_rows; input_row++)
            {
                // It seems fastest to make a separate pass for each component.
                byte[] inptr = input_buf[in_row_index + input_row];
                for (int ci = 0; ci < nc; ci++)
                {
                    byte[] outptr = output_buf[ci][output_row];
                    for (uint col = 0, off = (uint)ci; col < num_cols; col++, off += (uint)nc)
                    {
                        outptr[col] = inptr[off];
                    }
                }
                output_row++;
            }
        }
Example #16
0
		// Differencers for the all rows but the first in a scan or restart interval.
		// The first sample in the row is differenced using the vertical
		// predictor (2). The rest of the samples are differenced using the
		// predictor specified in the scan header.
		static void jpeg_difference1(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;

			int samp=input_buf[0];
			diff_buf[0]=samp-prev_row[0];

			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);
			}
		}
Example #17
0
        // Initialize for a processing pass.
        static void start_pass_coef(jpeg_compress cinfo, J_BUF_MODE pass_mode)
        {
            jpeg_lossy_c_codec lossyc = (jpeg_lossy_c_codec)cinfo.coef;
            c_coef_controller  coef   = (c_coef_controller)lossyc.coef_private;

            coef.iMCU_row_num = 0;
            start_iMCU_row_c_coef(cinfo);

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

#if FULL_COEF_BUFFER_SUPPORTED
            case J_BUF_MODE.JBUF_SAVE_AND_PASS:
                if (coef.whole_image[0] == null)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
                }
                lossyc.compress_data = compress_first_pass_coef;
                break;

            case J_BUF_MODE.JBUF_CRANK_DEST:
                if (coef.whole_image[0] == null)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
                }
                lossyc.compress_data = compress_output_coef;
                break;
#endif
            default:
                ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE);
                break;
            }
        }
Example #18
0
        // Initialize main buffer controller.
        static void jinit_c_main_controller(jpeg_compress cinfo, bool need_full_buffer)
        {
            my_c_main_controller main = null;

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

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

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

                // Allocate a strip buffer for each component
                for (int ci = 0; ci < cinfo.num_components; ci++)
                {
                    jpeg_component_info compptr = cinfo.comp_info[ci];
                    main.buffer[ci] = alloc_sarray(cinfo, compptr.width_in_blocks * DCT_size, (uint)(compptr.v_samp_factor * DCT_size));
                }
            }
        }
Example #19
0
        // *************** Cases other than RGB -> YCbCr *************

        // Convert some rows of samples to the JPEG colorspace.
        // This version handles RGB->grayscale conversion, which is the same
        // as the RGB->Y portion of RGB->YCbCr.
        // We assume rgb_ycc_start has been called (we only use the Y tables).
        static void rgb_gray_convert(jpeg_compress cinfo, byte[][] input_buf, uint in_row_index, byte[][][] output_buf, uint output_row, int num_rows)
        {
            my_color_converter cconvert = (my_color_converter)cinfo.cconvert;
            int r, g, b;

            int[] ctab = cconvert.rgb_ycc_tab;
            uint  num_cols = cinfo.image_width;

            for (uint input_row = 0; input_row < num_rows; input_row++)
            {
                byte[] inptr  = input_buf[in_row_index + input_row];
                byte[] outptr = output_buf[0][output_row];
                output_row++;
                for (uint col = 0, off = 0; col < num_cols; col++, off += RGB_PIXELSIZE)
                {
                    r           = inptr[off + RGB_RED];
                    g           = inptr[off + RGB_GREEN];
                    b           = inptr[off + RGB_BLUE];
                    outptr[col] = (byte)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + ctab[b + B_Y_OFF]) >> SCALEBITS);       // Y
                }
            }
        }
Example #20
0
        // Initialize for a processing pass.
        static void start_pass_c_main(jpeg_compress cinfo, J_BUF_MODE pass_mode)
        {
            my_c_main_controller main = (my_c_main_controller)cinfo.main;

            // Do nothing in raw-data mode.
            if (cinfo.raw_data_in)
            {
                return;
            }

            main.cur_iMCU_row = 0;                      // initialize counters
            main.rowgroup_ctr = 0;
            main.suspended    = false;
            main.pass_mode    = pass_mode;              // save mode for use by process_data

            switch (pass_mode)
            {
            case J_BUF_MODE.JBUF_PASS_THRU: main.process_data = process_data_simple_c_main; break;

            default: ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_BUFFER_MODE); break;
            }
        }
Example #21
0
		// Emit a SOF marker
		static void emit_sof(jpeg_compress cinfo, JPEG_MARKER code)
		{
			emit_marker(cinfo, code);

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

			// Make sure image isn't bigger than SOF field can handle
			if(cinfo.image_height>65535||cinfo.image_width>65535) ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_IMAGE_TOO_BIG, 65535);

			emit_byte(cinfo, cinfo.data_precision);
			emit_2bytes(cinfo, (int)cinfo.image_height);
			emit_2bytes(cinfo, (int)cinfo.image_width);

			emit_byte(cinfo, cinfo.num_components);

			for(int ci=0; ci<cinfo.num_components; ci++)
			{
				emit_byte(cinfo, cinfo.comp_info[ci].component_id);
				emit_byte(cinfo, (cinfo.comp_info[ci].h_samp_factor<<4)+cinfo.comp_info[ci].v_samp_factor);
				emit_byte(cinfo, cinfo.comp_info[ci].quant_tbl_no);
			}
		}
Example #22
0
		// Emit a DAC marker
		// Since the useful info is so small, we want to emit all the tables in
		// one DAC marker. Therefore this routine does its own scan of the table.
		static void emit_dac(jpeg_compress cinfo)
		{
#if C_ARITH_CODING_SUPPORTED
			byte[] dc_in_use=new byte[NUM_ARITH_TBLS];
			byte[] ac_in_use=new byte[NUM_ARITH_TBLS];

			for(int i=0; i<NUM_ARITH_TBLS; i++) dc_in_use[i]=ac_in_use[i]=0;

			for(int i=0; i<cinfo.comps_in_scan; i++)
			{
				jpeg_component_info compptr=cinfo.cur_comp_info[i];
				// DC needs no table for refinement scan
				if(cinfo.Ss==0&&cinfo.Ah==0) dc_in_use[compptr.dc_tbl_no]=1;
				// AC needs no table when not present
				if(cinfo.Se!=0) ac_in_use[compptr.ac_tbl_no]=1;
			}

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

			emit_marker(cinfo, JPEG_MARKER.M_DAC);
			emit_2bytes(cinfo, length*2+2);

			for(int i=0; i<NUM_ARITH_TBLS; i++)
			{
				if(dc_in_use[i]!=0)
				{
					emit_byte(cinfo, i);
					emit_byte(cinfo, cinfo.arith_dc_L[i]+(cinfo.arith_dc_U[i]<<4));
				}
				if(ac_in_use[i]!=0)
				{
					emit_byte(cinfo, i+0x10);
					emit_byte(cinfo, cinfo.arith_ac_K[i]);
				}
			}
#endif // C_ARITH_CODING_SUPPORTED
		}
Example #23
0
		// Emit an Adobe APP14 marker
		static void emit_adobe_app14(jpeg_compress cinfo)
		{
			// Length of APP14 block	(2 bytes)
			// Block ID					(5 bytes - ASCII "Adobe")
			// Version Number			(2 bytes - currently 100)
			// Flags0					(2 bytes - currently 0)
			// Flags1					(2 bytes - currently 0)
			// Color transform			(1 byte)
			//
			// Although Adobe TN 5116 mentions Version = 101, all the Adobe files
			// now in circulation seem to use Version = 100, so that's what we write.
			//
			// We write the color transform byte as 1 if the JPEG color space is
			// YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with
			// whether the encoder performed a transformation, which is pretty useless.
			emit_marker(cinfo, JPEG_MARKER.M_APP14);

			emit_2bytes(cinfo, 2+5+2+2+2+1); // length

			emit_byte(cinfo, 0x41);	// Identifier: ASCII "Adobe"
			emit_byte(cinfo, 0x64);
			emit_byte(cinfo, 0x6F);
			emit_byte(cinfo, 0x62);
			emit_byte(cinfo, 0x65);
			emit_2bytes(cinfo, 100);	// Version
			emit_2bytes(cinfo, 0);		// Flags0
			emit_2bytes(cinfo, 0);		// Flags1
			switch(cinfo.jpeg_color_space)
			{
				case J_COLOR_SPACE.JCS_YCbCr: emit_byte(cinfo, 1);	// Color transform = 1
					break;
				case J_COLOR_SPACE.JCS_YCCK: emit_byte(cinfo, 2);	// Color transform = 2
					break;
				default: emit_byte(cinfo, 0);						// Color transform = 0
					break;
			}
		}
Example #24
0
		// Emit a EXIF-compliant APP1 marker
		static void emit_exif_app1(jpeg_compress cinfo)
		{
			byte[] data=cinfo.exif.Generate();
			if(data==null) return;
			if(data.Length<8) return; // at least the TIFF header must be written completely

			// Length of APP1 block	(2 bytes)
			// Block ID				(4 bytes - ASCII "Exif")
			// Zero byte			(1 byte to terminate the ID string)
			// Zero byte			(1 byte padding)
			// Data					(n bytes)
			emit_marker(cinfo, JPEG_MARKER.M_APP1);

			emit_2bytes(cinfo, 2+4+1+1+data.Length); // length

			emit_byte(cinfo, 0x45);	// Identifier: ASCII "Exif"
			emit_byte(cinfo, 0x78);
			emit_byte(cinfo, 0x69);
			emit_byte(cinfo, 0x66);
			emit_byte(cinfo, 0);	// NULL
			emit_byte(cinfo, 0);	// Padding

			foreach(byte b in data) emit_byte(cinfo, b);
		}
Example #25
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 #26
0
		// NOTE: Uncomment the following #define if you want to use the
		// given formula for calculating the AC conditioning parameter Kx
		// for spectral selection progressive coding in section G.1.3.2
		// of the spec (Kx = Kmin + SRL (8 + Se - Kmin) 4).
		// Although the spec and P&M authors claim that this "has proven
		// to give good results for 8 bit precision samples", I'm not
		// convinced yet that this is really beneficial.
		// Early tests gave only very marginal compression enhancements
		// (a few - around 5 or so - bytes even for very large files),
		// which would turn out rather negative if we'd suppress the
		// DAC (Define Arithmetic Conditioning) marker segments for
		// the default parameters in the future.
		// Note that currently the marker writing module emits 12-byte
		// DAC segments for a full-component scan in a color image.
		// This is not worth worrying about IMHO. However, since the
		// spec defines the default values to be used if the tables
		// are omitted (unlike Huffman tables, which are required
		// anyway), one might optimize this behaviour in the future,
		// and then it would be disadvantageous to use custom tables if
		// they don't provide sufficient gain to exceed the DAC size.
		//
		// On the other hand, I'd consider it as a reasonable result
		// that the conditioning has no significant influence on the
		// compression performance. This means that the basic
		// statistical model is already rather stable.
		//
		// Thus, at the moment, we use the default conditioning values
		// anyway, and do not use the custom formula.
		//#define CALCULATE_SPECTRAL_CONDITIONING

		// Finish up at the end of an arithmetic-compressed scan.
		static void finish_pass_c_arith(jpeg_compress cinfo)
		{
			arith_entropy_encoder e=(arith_entropy_encoder)cinfo.coef;

			// Section D.1.8: Termination of encoding

			// Find the e.c in the coding interval with the largest
			// number of trailing zero bits
			int temp=(int)((uint)(e.a-1+e.c)&(uint)0xFFFF0000);
			if(temp<e.c) e.c=temp+0x8000;
			else e.c=temp;

			// Send remaining bytes to output
			e.c<<=e.ct;
			if(((uint)e.c&0xF8000000)!=0)
			{
				// One final overflow has to be handled
				if(e.buffer>=0)
				{
					if(e.zc!=0)
					{
						do emit_byte(cinfo, 0x00);
						while((--e.zc)!=0);
					}
					emit_byte(cinfo, e.buffer+1);
					if((e.buffer+1)==0xFF) emit_byte(cinfo, 0x00);
				}
				e.zc+=e.sc;	// carry-over converts stacked 0xFF bytes to 0x00
				e.sc=0;
			}
			else
			{
				if(e.buffer==0) ++e.zc;
				else if(e.buffer>=0)
				{
					if(e.zc!=0)
					{
						do emit_byte(cinfo, 0x00);
						while((--e.zc)!=0);
					}
					emit_byte(cinfo, e.buffer);
				}
				if(e.sc!=0)
				{
					if(e.zc!=0)
					{
						do emit_byte(cinfo, 0x00);
						while((--e.zc)!=0);
					}

					do
					{
						emit_byte(cinfo, 0xFF);
						emit_byte(cinfo, 0x00);
					} while((--e.sc)!=0);
				}
			}

			// Output final bytes only if they are not 0x00
			if((e.c&0x7FFF800)!=0)
			{
				if(e.zc!=0)	// output final pending zero bytes
				{
					do emit_byte(cinfo, 0x00);
					while((--e.zc)!=0);
				}
				emit_byte(cinfo, (e.c>>19)&0xFF);
				if(((e.c>>19)&0xFF)==0xFF) emit_byte(cinfo, 0x00);
				if((e.c&0x7F800)!=0)
				{
					emit_byte(cinfo, (e.c>>11)&0xFF);
					if(((e.c>>11)&0xFF)==0xFF) emit_byte(cinfo, 0x00);
				}
			}
		}
Example #27
0
		// Module initialization routine for arithmetic entropy encoding.
		static void jinit_arith_encoder(jpeg_compress cinfo)
		{
			arith_entropy_encoder entropy=cinfo.coef as arith_entropy_encoder;

			if(entropy==null)
			{
				try
				{
					entropy=new arith_entropy_encoder();
				}
				catch
				{
					ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
				}
				cinfo.coef=entropy;
			}

			entropy.entropy_start_pass=start_pass_c_arith;
			entropy.entropy_finish_pass=finish_pass_c_arith;

			// Mark tables unallocated
			for(int i=0; i<NUM_ARITH_TBLS; i++)
			{
				entropy.dc_stats[i]=null;
				entropy.ac_stats[i]=null;
			}
		}
Example #28
0
		// MCU encoding for AC initial scan (either spectral selection,
		// or first pass of successive approximation).
		static bool encode_mcu_AC_first_arith(jpeg_compress cinfo, short[][] MCU_data)
		{
			arith_entropy_encoder entropy=(arith_entropy_encoder)cinfo.coef;

			// Emit restart marker if needed
			if(cinfo.restart_interval!=0)
			{
				if(entropy.restarts_to_go==0)
				{
					emit_restart_arith(cinfo, entropy.next_restart_num);
					entropy.restarts_to_go=cinfo.restart_interval;
					entropy.next_restart_num++;
					entropy.next_restart_num&=7;
				}
				entropy.restarts_to_go--;
			}

			// Encode the MCU data block
			short[] block=MCU_data[0];
			int tbl=cinfo.cur_comp_info[0].ac_tbl_no;

			// Sections F.1.4.2 & F.1.4.4.2: Encoding of AC coefficients
			int k, ke, v;

			// Establish EOB (end-of-block) index
			for(ke=cinfo.Se+1; ke>1; ke--)
			{
				// We must apply the point transform by Al. For AC coefficients this
				// is an integer division with rounding towards 0. To do this portably
				// in C#, we shift after obtaining the absolute value.
				v=block[jpeg_natural_order[ke-1]];
				if(v>=0)
				{
					v>>=cinfo.Al;
					if(v!=0) break;
				}
				else
				{
					v=-v;
					v>>=cinfo.Al;
					if(v!=0) break;
				}
			}

			// Figure F.5: Encode_AC_Coefficients
			for(k=cinfo.Ss; k<ke; k++)
			{
				byte[] st=entropy.ac_stats[tbl];
				int st_ind=3*(k-1);
				arith_encode(cinfo, ref st[st_ind], 0);		// EOB decision
				entropy.ac_stats[tbl][245]=0;
				for(; ; )
				{
					v=block[jpeg_natural_order[k]];
					if(v>=0)
					{
						v>>=cinfo.Al;
						if(v!=0)
						{
							arith_encode(cinfo, ref st[st_ind+1], 1);
							arith_encode(cinfo, ref entropy.ac_stats[tbl][245], 0);
							break;
						}
					}
					else
					{
						v=-v;
						v>>=cinfo.Al;
						if(v!=0)
						{
							arith_encode(cinfo, ref st[st_ind+1], 1);
							arith_encode(cinfo, ref entropy.ac_stats[tbl][245], 1);
							break;
						}
					}
					arith_encode(cinfo, ref st[st_ind+1], 0); st_ind+=3; k++;
				}
				st_ind+=2;

				// Figure F.8: Encoding the magnitude category of v
				int m=0;
				v--;
				if(v!=0)
				{
					arith_encode(cinfo, ref st[st_ind], 1);
					m=1;
					int v2=v;
					v2>>=1;
					if(v2!=0)
					{
						arith_encode(cinfo, ref st[st_ind], 1);
						m<<=1;
						st=entropy.ac_stats[tbl];
						st_ind=(k<=cinfo.arith_ac_K[tbl]?189:217);
						while((v2>>=1)!=0)
						{
							arith_encode(cinfo, ref st[st_ind], 1);
							m<<=1;
							st_ind+=1;
						}
					}
				}
				arith_encode(cinfo, ref st[st_ind], 0);

				// Figure F.9: Encoding the magnitude bit pattern of v
				st_ind+=14;
				while((m>>=1)!=0) arith_encode(cinfo, ref st[st_ind], ((m&v)!=0)?1:0);
			}

			// Encode EOB decision only if k <= cinfo.Se
			if(k<=cinfo.Se)
			{
				byte[] st=entropy.ac_stats[tbl];
				int st_ind=3*(k-1);
				arith_encode(cinfo, ref st[st_ind], 1);
			}

			return true;
		}
Example #29
0
		// MCU encoding for AC successive approximation refinement scan.
		static bool encode_mcu_AC_refine_arith(jpeg_compress cinfo, short[][] MCU_data)
		{
			arith_entropy_encoder entropy=(arith_entropy_encoder)cinfo.coef;

			// Emit restart marker if needed
			if(cinfo.restart_interval!=0)
			{
				if(entropy.restarts_to_go==0)
				{
					emit_restart_arith(cinfo, entropy.next_restart_num);
					entropy.restarts_to_go=cinfo.restart_interval;
					entropy.next_restart_num++;
					entropy.next_restart_num&=7;
				}
				entropy.restarts_to_go--;
			}

			// Encode the MCU data block
			short[] block=MCU_data[0];
			int tbl=cinfo.cur_comp_info[0].ac_tbl_no;

			// Section G.1.3.3: Encoding of AC coefficients
			int k, ke, kex, v;

			// Establish EOB (end-of-block) index
			for(ke=cinfo.Se+1; ke>1; ke--)
			{
				// We must apply the point transform by Al. For AC coefficients this
				// is an integer division with rounding towards 0. To do this portably
				// in C#, we shift after obtaining the absolute value.
				v=block[jpeg_natural_order[ke-1]];
				if(v>=0)
				{
					v>>=cinfo.Al;
					if(v!=0) break;
				}
				else
				{
					v=-v;
					v>>=cinfo.Al;
					if(v!=0) break;
				}
			}

			// Establish EOBx (previous stage end-of-block) index
			for(kex=ke; kex>1; kex--)
			{
				v=block[jpeg_natural_order[kex-1]];
				if(v>=0)
				{
					v>>=cinfo.Ah;
					if(v!=0) break;
				}
				else
				{
					v=-v;
					v>>=cinfo.Ah;
					if(v!=0) break;
				}
			}

			// Figure G.10: Encode_AC_Coefficients_SA
			for(k=cinfo.Ss; k<ke; k++)
			{
				byte[] st=entropy.ac_stats[tbl];
				int st_ind=3*(k-1);
				if(k>=kex) arith_encode(cinfo, ref st[st_ind], 0);	// EOB decision
				entropy.ac_stats[tbl][245]=0;
				for(; ; )
				{
					v=block[jpeg_natural_order[k]];
					if(v>=0)
					{
						v>>=cinfo.Al;
						if(v!=0)
						{
							if((v>>1)!=0) arith_encode(cinfo, ref st[st_ind+2], (v&1)); // previously nonzero coef
							else
							{ // newly nonzero coef
								arith_encode(cinfo, ref st[st_ind+1], 1);
								arith_encode(cinfo, ref entropy.ac_stats[tbl][245], 0);
							}
							break;
						}
					}
					else
					{
						v=-v;
						v>>=cinfo.Al;
						if(v!=0)
						{
							if((v>>1)!=0) arith_encode(cinfo, ref st[st_ind+2], (v&1)); // previously nonzero coef
							else
							{ // newly nonzero coef
								arith_encode(cinfo, ref st[st_ind+1], 1);
								arith_encode(cinfo, ref entropy.ac_stats[tbl][245], 1);
							}
							break;
						}
					}
					arith_encode(cinfo, ref st[st_ind+1], 0); st_ind+=3; k++;
				}
			}

			// Encode EOB decision only if k <= cinfo.Se
			if(k<=cinfo.Se)
			{
				byte[] st=entropy.ac_stats[tbl];
				int st_ind=3*(k-1);
				arith_encode(cinfo, ref st[st_ind], 1);
			}

			return true;
		}
Example #30
0
		// Write frame header.
		// This consists of DQT and SOFn markers.
		// Note that we do not emit the SOF until we have emitted the DQT(s).
		// This avoids compatibility problems with incorrect implementations that
		// try to error-check the quant table numbers as soon as they see the SOF.
		static void write_frame_header(jpeg_compress cinfo)
		{
			int prec=0;
			bool is_baseline;

			if(cinfo.process!=J_CODEC_PROCESS.JPROC_LOSSLESS)
			{
				// Emit DQT for each quantization table.
				// Note that emit_dqt() suppresses any duplicate tables.
				prec=0;
				for(int ci=0; ci<cinfo.num_components; ci++)
				{
					prec+=emit_dqt(cinfo, cinfo.comp_info[ci].quant_tbl_no);
				}
				// now prec is nonzero iff there are any 16-bit quant tables.
			}

			// Check for a non-baseline specification.
			// Note we assume that Huffman table numbers won't be changed later.
			if(cinfo.arith_code||cinfo.process!=J_CODEC_PROCESS.JPROC_SEQUENTIAL||cinfo.data_precision!=8)
			{
				is_baseline=false;
			}
			else
			{
				is_baseline=true;
				for(int ci=0; ci<cinfo.num_components; ci++)
				{
					if(cinfo.comp_info[ci].dc_tbl_no>1||cinfo.comp_info[ci].ac_tbl_no>1)
					{
						is_baseline=false;
						break;
					}
				}
				if(prec!=0&&is_baseline)
				{
					is_baseline=false;
					// If it's baseline except for quantizer size, warn the user
					TRACEMS(cinfo, 0, J_MESSAGE_CODE.JTRC_16BIT_TABLES);
				}
			}

			// Emit the proper SOF marker
			if(cinfo.arith_code)
			{
				if(cinfo.process==J_CODEC_PROCESS.JPROC_PROGRESSIVE)
					emit_sof(cinfo, JPEG_MARKER.M_SOF10);	// SOF code for progressive arithmetic
				else if(cinfo.process==J_CODEC_PROCESS.JPROC_SEQUENTIAL)
					emit_sof(cinfo, JPEG_MARKER.M_SOF9);	// SOF code for sequential arithmetic
				else ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOTIMPL);
			}
			else
			{
				if(cinfo.process==J_CODEC_PROCESS.JPROC_PROGRESSIVE)
					emit_sof(cinfo, JPEG_MARKER.M_SOF2);	// SOF code for progressive Huffman
				else if(cinfo.process==J_CODEC_PROCESS.JPROC_LOSSLESS)
					emit_sof(cinfo, JPEG_MARKER.M_SOF3);	// SOF code for lossless Huffman
				else if(is_baseline)
					emit_sof(cinfo, JPEG_MARKER.M_SOF0);	// SOF code for baseline implementation
				else
					emit_sof(cinfo, JPEG_MARKER.M_SOF1);	// SOF code for non-baseline Huffman file
			}
		}
Example #31
0
		// Emit a restart marker & resynchronize predictions.
		static void emit_restart_arith(jpeg_compress cinfo, int restart_num)
		{
			arith_entropy_encoder entropy=(arith_entropy_encoder)cinfo.coef;

			finish_pass_c_arith(cinfo);

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

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

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

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

			// Reset arithmetic encoding variables
			entropy.c=0;
			entropy.a=0x10000;
			entropy.sc=0;
			entropy.zc=0;
			entropy.ct=11;
			entropy.buffer=-1;	// empty
		}
Example #32
0
		// *************** Cases other than RGB -> YCbCr *************
		
		// Convert some rows of samples to the JPEG colorspace.
		// This version handles RGB->grayscale conversion, which is the same
		// as the RGB->Y portion of RGB->YCbCr.
		// We assume rgb_ycc_start has been called (we only use the Y tables).
		static void rgb_gray_convert(jpeg_compress cinfo, byte[][] input_buf, uint in_row_index, byte[][][] output_buf, uint output_row, int num_rows)
		{
			my_color_converter cconvert=(my_color_converter)cinfo.cconvert;
			int r, g, b;
			int[] ctab=cconvert.rgb_ycc_tab;
			uint num_cols=cinfo.image_width;

			for(uint input_row=0; input_row<num_rows; input_row++)
			{
				byte[] inptr=input_buf[in_row_index+input_row];
				byte[] outptr=output_buf[0][output_row];
				output_row++;
				for(uint col=0, off=0; col<num_cols; col++, off+=RGB_PIXELSIZE)
				{
					r=inptr[off+RGB_RED];
					g=inptr[off+RGB_GREEN];
					b=inptr[off+RGB_BLUE];
					outptr[col]=(byte)((ctab[r+R_Y_OFF]+ctab[g+G_Y_OFF]+ctab[b+B_Y_OFF])>>SCALEBITS); // Y
				}
			}
		}
Example #33
0
        // Process some data in the single-pass case.
        // We process the equivalent of one fully interleaved MCU row ("iMCU" row)
        // per call, ie, v_samp_factor block rows for each component in the image.
        // Returns true if the iMCU row is completed, false if suspended.
        //
        // NB: input_buf contains a plane for each component in image,
        // which we index according to the component's SOF position.
        static bool compress_data_coef(jpeg_compress cinfo, byte[][][] input_buf)
        {
            jpeg_lossy_c_codec lossyc = (jpeg_lossy_c_codec)cinfo.coef;
            c_coef_controller  coef   = (c_coef_controller)lossyc.coef_private;
            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 = 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
                {
                    // Determine where data comes from in input_buf and do the DCT thing.
                    // Each call on forward_DCT processes a horizontal row of DCT blocks
                    // as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks
                    // sequentially. Dummy blocks at the right or bottom edge are filled in
                    // specially. The data in them does not matter for image reconstruction,
                    // so we fill them with values that will encode to the smallest amount of
                    // data, viz: all zeroes in the AC entries, DC entries equal to previous
                    // block's DC value. (Thanks to Thomas Kinsman for this idea.)
                    int blkn = 0;
                    for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
                    {
                        jpeg_component_info compptr = cinfo.cur_comp_info[ci];
                        int blockcnt = (MCU_col_num < last_MCU_col)?compptr.MCU_width:compptr.last_col_width;

                        uint xpos = MCU_col_num * (uint)compptr.MCU_sample_width;
                        uint ypos = (uint)yoffset * DCTSIZE;                     // ypos == (yoffset+yindex) * DCTSIZE

                        for (int yindex = 0; yindex < compptr.MCU_height; yindex++)
                        {
                            if (coef.iMCU_row_num < last_iMCU_row || yoffset + yindex < compptr.last_row_height)
                            {
                                lossyc.fdct_forward_DCT(cinfo, compptr, input_buf[compptr.component_index], coef.MCU_buffer, blkn, ypos, xpos, (uint)blockcnt);
                                if (blockcnt < compptr.MCU_width)
                                {
                                    // Create some dummy blocks at the right edge of the image.
                                    for (int bi = blockcnt; bi < compptr.MCU_width; bi++)
                                    {
                                        short[] block = coef.MCU_buffer[blkn + bi];
                                        for (int i = 1; i < DCTSIZE2; i++)
                                        {
                                            block[i] = 0;                                                               // ACs
                                        }
                                        block[0] = coef.MCU_buffer[blkn + bi - 1][0];                                   // DCs
                                    }
                                }
                            }
                            else
                            {
                                // Create a row of dummy blocks at the bottom of the image.
                                for (int bi = 0; bi < compptr.MCU_width; bi++)
                                {
                                    short[] block = coef.MCU_buffer[blkn + bi];
                                    for (int i = 1; i < DCTSIZE2; i++)
                                    {
                                        block[i] = 0;                                                        // ACs
                                    }
                                    block[0] = coef.MCU_buffer[blkn - 1][0];                                 // DCs
                                }
                            }
                            blkn += compptr.MCU_width;
                            ypos += DCTSIZE;
                        }
                    }

                    // Try to write the MCU. In event of a suspension failure, we will
                    // re-DCT the MCU on restart (a bit inefficient, could be fixed...)
                    if (!lossyc.entropy_encode_mcu(cinfo, coef.MCU_buffer))
                    {
                        // Suspension forced; update state counters and exit
                        coef.MCU_vert_offset = yoffset;
                        coef.mcu_ctr         = MCU_col_num;
                        return(false);
                    }
                }

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

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

            return(true);
        }
Example #34
0
		// Convert some rows of samples to the JPEG colorspace.
		// This version handles Adobe-style CMYK->YCCK conversion,
		// where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
		// conversion as above, while passing K (black) unchanged.
		// We assume rgb_ycc_start has been called.
		static void cmyk_ycck_convert(jpeg_compress cinfo, byte[][] input_buf, uint in_row_index, byte[][][] output_buf, uint output_row, int num_rows)
		{
			my_color_converter cconvert=(my_color_converter)cinfo.cconvert;
			int r, g, b;
			int[] ctab=cconvert.rgb_ycc_tab;
			uint num_cols=cinfo.image_width;

			for(uint input_row=0; input_row<num_rows; input_row++)
			{
				byte[] inptr=input_buf[in_row_index+input_row];
				byte[] outptr0=output_buf[0][output_row];
				byte[] outptr1=output_buf[1][output_row];
				byte[] outptr2=output_buf[2][output_row];
				byte[] outptr3=output_buf[3][output_row];
				output_row++;
				for(uint col=0, off=0; col<num_cols; col++, off+=4)
				{
					r=MAXJSAMPLE-inptr[off+0];
					g=MAXJSAMPLE-inptr[off+1];
					b=MAXJSAMPLE-inptr[off+2];
					// K passes through as-is
					outptr3[col]=inptr[off+3];
					// If the inputs are 0..MAXJSAMPLE, the outputs of these equations
					// must be too; we do not need an explicit range-limiting operation.
					outptr0[col]=(byte)((ctab[r+R_Y_OFF]+ctab[g+G_Y_OFF]+ctab[b+B_Y_OFF])>>SCALEBITS); // Y
					outptr1[col]=(byte)((ctab[r+R_CB_OFF]+ctab[g+G_CB_OFF]+ctab[b+B_CB_OFF])>>SCALEBITS); // Cb
					outptr2[col]=(byte)((ctab[r+R_CR_OFF]+ctab[g+G_CR_OFF]+ctab[b+B_CR_OFF])>>SCALEBITS); // Cr
				}
			}
		}
Example #35
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 #36
0
        // MCU encoding for AC successive approximation refinement scan.
        static bool encode_mcu_AC_refine_phuff(jpeg_compress cinfo, short[][] MCU_data)
        {
            jpeg_lossy_c_codec    lossyc  = (jpeg_lossy_c_codec)cinfo.coef;
            phuff_entropy_encoder entropy = (phuff_entropy_encoder)lossyc.entropy_private;
            int r;

            byte[] BR_buffer;
            uint   BR;
            int    Se = cinfo.Se;
            int    Al = cinfo.Al;

            int[] absvalues = new int[DCTSIZE2];

            entropy.output_bytes     = cinfo.dest.output_bytes;
            entropy.next_output_byte = cinfo.dest.next_output_byte;
            entropy.free_in_buffer   = cinfo.dest.free_in_buffer;

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

            // Encode the MCU data block
            short[] block = MCU_data[0];

            // It is convenient to make a pre-pass to determine the transformed
            // coefficients' absolute values and the EOB position.
            int EOB = 0;
            int k;

            for (k = cinfo.Ss; k <= Se; k++)
            {
                int temp = block[jpeg_natural_order[k]];
                // We must apply the point transform by Al. For AC coefficients this
                // is an integer division with rounding towards 0. To do this portably
                // in C, we shift after obtaining the absolute value.
                if (temp < 0)
                {
                    temp = -temp;                       // temp is abs value of input
                }
                temp       >>= Al;                      // apply the point transform
                absvalues[k] = temp;                    // save abs value for main pass
                if (temp == 1)
                {
                    EOB = k;                                    // EOB = index of last newly-nonzero coef
                }
            }

            // Encode the AC coefficients per section G.1.2.3, fig. G.7
            r         = 0;                      // r = run length of zeros
            BR        = 0;                      // BR = count of buffered bits added now
            BR_buffer = entropy.bit_buffer;     // Append bits to buffer
            uint BR_buffer_ind = entropy.BE;

            for (k = cinfo.Ss; k <= Se; k++)
            {
                int temp = absvalues[k];
                if (temp == 0)
                {
                    r++;
                    continue;
                }

                // Emit any required ZRLs, but not if they can be folded into EOB
                while (r > 15 && k <= EOB)
                {
                    // emit any pending EOBRUN and the BE correction bits
                    emit_eobrun(entropy);

                    // Emit ZRL
                    emit_symbol(entropy, entropy.ac_tbl_no, 0xF0);
                    r -= 16;

                    // Emit buffered correction bits that must be associated with ZRL
                    emit_buffered_bits(entropy, BR_buffer, BR_buffer_ind, BR);
                    BR_buffer     = entropy.bit_buffer;               // BE bits are gone now
                    BR_buffer_ind = 0;
                    BR            = 0;
                }

                // If the coef was previously nonzero, it only needs a correction bit.
                // NOTE: a straight translation of the spec's figure G.7 would suggest
                // that we also need to test r > 15. But if r > 15, we can only get here
                // if k > EOB, which implies that this coefficient is not 1.
                if (temp > 1)
                {
                    // The correction bit is the next bit of the absolute value.
                    BR_buffer[BR_buffer_ind + BR++] = (byte)(temp & 1);
                    continue;
                }

                // Emit any pending EOBRUN and the BE correction bits
                emit_eobrun(entropy);

                // Count/emit Huffman symbol for run length / number of bits
                emit_symbol(entropy, entropy.ac_tbl_no, (r << 4) + 1);

                // Emit output bit for newly-nonzero coef
                temp = (block[jpeg_natural_order[k]] < 0)?0:1;
                emit_bits(entropy, (uint)temp, 1);

                // Emit buffered correction bits that must be associated with this code
                emit_buffered_bits(entropy, BR_buffer, BR_buffer_ind, BR);
                BR_buffer     = entropy.bit_buffer;           // BE bits are gone now
                BR_buffer_ind = 0;
                BR            = 0;
                r             = 0;   // reset zero run length
            }

            if (r > 0 || BR > 0)      // If there are trailing zeroes,
            {
                entropy.EOBRUN++;     // count an EOB
                entropy.BE += BR;     // concat my correction bits to older ones
                // We force out the EOB if we risk either:
                // 1. overflow of the EOB counter;
                // 2. overflow of the correction bit buffer during the next MCU.
                if (entropy.EOBRUN == 0x7FFF || entropy.BE > (MAX_CORR_BITS - DCTSIZE2 + 1))
                {
                    emit_eobrun(entropy);
                }
            }

            cinfo.dest.output_bytes     = entropy.output_bytes;
            cinfo.dest.next_output_byte = entropy.next_output_byte;
            cinfo.dest.free_in_buffer   = entropy.free_in_buffer;

            // 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(true);
        }
Example #37
0
		// Module initialization routine for input colorspace conversion.
		static void jinit_color_converter(jpeg_compress cinfo)
		{
			my_color_converter cconvert=null;
			try
			{
				cinfo.cconvert=cconvert=new my_color_converter();
			}
			catch
			{
				ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
			}

			// set start_pass to null method until we find out differently
			cconvert.start_pass=null_method;

			// Make sure input_components agrees with in_color_space
			switch(cinfo.in_color_space)
			{
				case J_COLOR_SPACE.JCS_GRAYSCALE:
					if(cinfo.input_components!=1) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_IN_COLORSPACE);
					break;
				case J_COLOR_SPACE.JCS_RGB:
				case J_COLOR_SPACE.JCS_YCbCr:
					if(cinfo.input_components!=3) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_IN_COLORSPACE);
					break;
				case J_COLOR_SPACE.JCS_CMYK:
				case J_COLOR_SPACE.JCS_YCCK:
					if(cinfo.input_components!=4) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_IN_COLORSPACE);
					break;
				default: // JCS_UNKNOWN can be anything
					if(cinfo.input_components<1) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_IN_COLORSPACE);
					break;
			}

			// Check num_components, set conversion method based on requested space
			switch(cinfo.jpeg_color_space)
			{
				case J_COLOR_SPACE.JCS_GRAYSCALE:
					if(cinfo.num_components!=1) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
					if(cinfo.in_color_space==J_COLOR_SPACE.JCS_GRAYSCALE) cconvert.color_convert=grayscale_convert;
					else if(cinfo.in_color_space==J_COLOR_SPACE.JCS_RGB)
					{
						cconvert.start_pass=rgb_ycc_start;
						cconvert.color_convert=rgb_gray_convert;
					}
					else if(cinfo.in_color_space==J_COLOR_SPACE.JCS_YCbCr) cconvert.color_convert=grayscale_convert;
					else ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
					break;
				case J_COLOR_SPACE.JCS_RGB:
					if(cinfo.num_components!=3) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
					if(cinfo.in_color_space==J_COLOR_SPACE.JCS_RGB&&RGB_PIXELSIZE==3) cconvert.color_convert=null_convert;
					else ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
					break;
				case J_COLOR_SPACE.JCS_YCbCr:
					if(cinfo.num_components!=3) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
					if(cinfo.in_color_space==J_COLOR_SPACE.JCS_RGB)
					{
						cconvert.start_pass=rgb_ycc_start;
						cconvert.color_convert=rgb_ycc_convert;
					}
					else if(cinfo.in_color_space==J_COLOR_SPACE.JCS_YCbCr) cconvert.color_convert=null_convert;
					else ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
					break;
				case J_COLOR_SPACE.JCS_CMYK:
					if(cinfo.num_components!=4) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
					if(cinfo.in_color_space==J_COLOR_SPACE.JCS_CMYK) cconvert.color_convert=null_convert;
					else ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
					break;
				case J_COLOR_SPACE.JCS_YCCK:
					if(cinfo.num_components!=4)
						ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
					if(cinfo.in_color_space==J_COLOR_SPACE.JCS_CMYK)
					{
						cconvert.start_pass=rgb_ycc_start;
						cconvert.color_convert=cmyk_ycck_convert;
					}
					else if(cinfo.in_color_space==J_COLOR_SPACE.JCS_YCCK) cconvert.color_convert=null_convert;
					else ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
					break;
				default: // allow null conversion of JCS_UNKNOWN
					if(cinfo.jpeg_color_space!=cinfo.in_color_space||
					cinfo.num_components!=cinfo.input_components) ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
					cconvert.color_convert=null_convert;
					break;
			}
		}
Example #38
0
		// Empty method for start_pass.
		static void null_method(jpeg_compress cinfo)
		{
			// no work needed
		}
Example #39
0
        // MCU encoding for AC initial scan (either spectral selection,
        // or first pass of successive approximation).
        static bool encode_mcu_AC_first_phuff(jpeg_compress cinfo, short[][] MCU_data)
        {
            jpeg_lossy_c_codec    lossyc  = (jpeg_lossy_c_codec)cinfo.coef;
            phuff_entropy_encoder entropy = (phuff_entropy_encoder)lossyc.entropy_private;
            int Se = cinfo.Se;
            int Al = cinfo.Al;

            entropy.output_bytes     = cinfo.dest.output_bytes;
            entropy.next_output_byte = cinfo.dest.next_output_byte;
            entropy.free_in_buffer   = cinfo.dest.free_in_buffer;

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

            // Encode the MCU data block
            short[] block = MCU_data[0];

            // Encode the AC coefficients per section G.1.2.2, fig. G.3
            int r = 0;           // r = run length of zeros

            for (int k = cinfo.Ss; k <= Se; k++)
            {
                int temp = block[jpeg_natural_order[k]];
                if (temp == 0)
                {
                    r++;
                    continue;
                }

                // We must apply the point transform by Al. For AC coefficients this
                // is an integer division with rounding towards 0. To do this portably
                // in C, we shift after obtaining the absolute value; so the code is
                // interwoven with finding the abs value (temp) and output bits (temp2).
                int temp2;
                if (temp < 0)
                {
                    temp   = -temp;                             // temp is abs value of input
                    temp >>= Al;                                // apply the point transform
                    // For a negative coef, want temp2 = bitwise complement of abs(coef)
                    temp2 = ~temp;
                }
                else
                {
                    temp >>= Al;                                // apply the point transform
                    temp2  = temp;
                }

                // Watch out for case that nonzero coef is zero after point transform
                if (temp == 0)
                {
                    r++;
                    continue;
                }

                // Emit any pending EOBRUN
                if (entropy.EOBRUN > 0)
                {
                    emit_eobrun(entropy);
                }

                // if run length > 15, must emit special run-length-16 codes (0xF0)
                while (r > 15)
                {
                    emit_symbol(entropy, entropy.ac_tbl_no, 0xF0);
                    r -= 16;
                }

                // Find the number of bits needed for the magnitude of the coefficient
                int nbits = 1;               // there must be at least one 1 bit
                while ((temp >>= 1) != 0)
                {
                    nbits++;
                }

                // Check for out-of-range coefficient values
                if (nbits > MAX_COEF_BITS)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_DCT_COEF);
                }

                // Count/emit Huffman symbol for run length / number of bits
                emit_symbol(entropy, entropy.ac_tbl_no, (r << 4) + nbits);

                // Emit that number of bits of the value, if positive,
                // or the complement of its magnitude, if negative.
                emit_bits(entropy, (uint)temp2, nbits);

                r = 0;               // reset zero run length
            }

            if (r > 0)            // If there are trailing zeroes,
            {
                entropy.EOBRUN++; // count an EOB
                if (entropy.EOBRUN == 0x7FFF)
                {
                    emit_eobrun(entropy);                                        // force it out to avoid overflow
                }
            }

            cinfo.dest.output_bytes     = entropy.output_bytes;
            cinfo.dest.next_output_byte = entropy.next_output_byte;
            cinfo.dest.free_in_buffer   = entropy.free_in_buffer;

            // 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(true);
        }
Example #40
0
 static bool need_optimization_pass_ls(jpeg_compress cinfo)
 {
     return(true);
 }
Example #41
0
		// Convert some rows of samples to the JPEG colorspace.
		// This version handles multi-component colorspaces without conversion.
		// We assume input_components == num_components.
		static void null_convert(jpeg_compress cinfo, byte[][] input_buf, uint in_row_index, byte[][][] output_buf, uint output_row, int num_rows)
		{
			int nc=cinfo.num_components;
			uint num_cols=cinfo.image_width;

			for(uint input_row=0; input_row<num_rows; input_row++)
			{
				// It seems fastest to make a separate pass for each component.
				byte[] inptr=input_buf[in_row_index+input_row];
				for(int ci=0; ci<nc; ci++)
				{
					byte[] outptr=output_buf[ci][output_row];
					for(uint col=0, off=(uint)ci; col<num_cols; col++, off+=(uint)nc) outptr[col]=inptr[off];
				}
				output_row++;
			}
		}
Example #42
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 #43
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 block rows for each component in the image.
        // This amount of data is read from the source buffer, DCT'd and quantized,
        // and saved into the arrays. We also generate suitable dummy blocks
        // as needed at the right and lower edges. (The dummy blocks are constructed
        // in the arrays, which have been padded appropriately.) This makes
        // it possible for subsequent passes not to worry about real vs. dummy blocks.
        //
        // We must also emit the data to the entropy encoder. This is conveniently
        // done by calling compress_output_coef() after we've loaded the current strip
        // of the arrays.
        //
        // NB: input_buf contains a plane for each component in image. All
        // components are DCT'd and loaded into the arrays in this pass.
        // However, it may be that only a subset of the components are emitted to
        // the entropy encoder during this first pass; be careful about looking
        // at the scan-dependent variables (MCU dimensions, etc).
        static bool compress_first_pass_coef(jpeg_compress cinfo, byte[][][] input_buf)
        {
            jpeg_lossy_c_codec lossyc = (jpeg_lossy_c_codec)cinfo.coef;
            c_coef_controller  coef   = (c_coef_controller)lossyc.coef_private;

            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];

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

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

                uint blocks_across = compptr.width_in_blocks;
                int  h_samp_factor = compptr.h_samp_factor;

                // Count number of dummy blocks to be added at the right margin.
                int ndummy = (int)(blocks_across % h_samp_factor);
                if (ndummy > 0)
                {
                    ndummy = h_samp_factor - ndummy;
                }

                // Perform DCT for all non-dummy blocks in this iMCU row. Each call
                // on forward_DCT processes a complete horizontal row of DCT blocks.
                for (int block_row = 0; block_row < block_rows; block_row++)
                {
                    short[][] row = buffer[buffer_ind + block_row];
                    lossyc.fdct_forward_DCT(cinfo, compptr, input_buf[ci], row, 0, (uint)(block_row * DCTSIZE), 0, blocks_across);
                    if (ndummy > 0)
                    {
                        // Create dummy blocks at the right edge of the image.
                        short lastDC = row[blocks_across - 1][0];
                        for (int bi = 0; bi < ndummy; bi++)
                        {
                            short[] block = row[blocks_across + bi];
                            for (int i = 1; i < DCTSIZE2; i++)
                            {
                                block[i] = 0;
                            }
                            block[0] = lastDC;
                        }
                    }
                }
                // If at end of image, create dummy block rows as needed.
                // The tricky part here is that within each MCU, we want the DC values
                // of the dummy blocks to match the last real block's DC value.
                // This squeezes a few more bytes out of the resulting file...
                if (coef.iMCU_row_num == last_iMCU_row)
                {
                    blocks_across += (uint)ndummy;                   // include lower right corner
                    uint MCUs_across = blocks_across / (uint)h_samp_factor;
                    for (int block_row = block_rows; block_row < compptr.v_samp_factor; block_row++)
                    {
                        short[][] thisblockrow     = buffer[buffer_ind + block_row];
                        short[][] lastblockrow     = buffer[buffer_ind + block_row - 1];
                        int       thisblockrow_ind = 0;
                        int       lastblockrow_ind = h_samp_factor - 1;

                        for (int j = 0; j < blocks_across; j++)
                        {
                            short[] block = thisblockrow[j];
                            for (int i = 0; i < DCTSIZE2; i++)
                            {
                                block[i] = 0;
                            }
                        }

                        for (uint MCUindex = 0; MCUindex < MCUs_across; MCUindex++)
                        {
                            short lastDC = lastblockrow[lastblockrow_ind][0];
                            for (int bi = 0; bi < h_samp_factor; bi++)
                            {
                                thisblockrow[thisblockrow_ind + bi][0] = lastDC;
                            }

                            thisblockrow_ind += h_samp_factor;                           // advance to next MCU in row
                            lastblockrow_ind += h_samp_factor;
                        }
                    }
                }
            }

            // 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 entropy encoder, sharing code with subsequent passes
            return(compress_output_coef(cinfo, input_buf));
        }
Example #44
0
		// Convert some rows of samples to the JPEG colorspace.
		//
		// Note that we change from the application's interleaved-pixel format
		// to our internal noninterleaved, one-plane-per-component format.
		// The input buffer is therefore three times as wide as the output buffer.
		//
		// A starting row offset is provided only for the output buffer. The caller
		// can easily adjust the passed input_buf value to accommodate any row
		// offset required on that side.
		static void rgb_ycc_convert(jpeg_compress cinfo, byte[][] input_buf, uint in_row_index, byte[][][] output_buf, uint output_row, int num_rows)
		{
			my_color_converter cconvert=(my_color_converter)cinfo.cconvert;
			int r, g, b;
			int[] ctab=cconvert.rgb_ycc_tab;
			uint num_cols=cinfo.image_width;

			for(uint input_row=0; input_row<num_rows; input_row++)
			{
				byte[] inptr=input_buf[in_row_index+input_row];
				byte[] outptr0=output_buf[0][output_row];
				byte[] outptr1=output_buf[1][output_row];
				byte[] outptr2=output_buf[2][output_row];
				output_row++;
				for(uint col=0, off=0; col<num_cols; col++, off+=RGB_PIXELSIZE)
				{
					r=inptr[off+RGB_RED];
					g=inptr[off+RGB_GREEN];
					b=inptr[off+RGB_BLUE];
					// If the inputs are 0..MAXJSAMPLE, the outputs of these equations
					// must be too; we do not need an explicit range-limiting operation.
					outptr0[col]=(byte)((ctab[r+R_Y_OFF]+ctab[g+G_Y_OFF]+ctab[b+B_Y_OFF])>>SCALEBITS); // Y
					outptr1[col]=(byte)((ctab[r+R_CB_OFF]+ctab[g+G_CB_OFF]+ctab[b+B_CB_OFF])>>SCALEBITS); // Cb
					outptr2[col]=(byte)((ctab[r+R_CR_OFF]+ctab[g+G_CR_OFF]+ctab[b+B_CR_OFF])>>SCALEBITS); // Cr
					//outptr0[col]=(byte)(0.299*r+0.587*g+0.114*b);
					//outptr1[col]=(byte)(-0.168736*r-0.331264*g+0.5*b+CENTERJSAMPLE);
					//outptr2[col]=(byte)(0.5*r-0.418688*g-0.081312*b+CENTERJSAMPLE);
				}
			}
		}
Example #45
0
		// The core arithmetic encoding routine (common in JPEG and JBIG).
		// This needs to go as fast as possible.
		// Machine-dependent optimization facilities
		// are not utilized in this portable implementation.
		// However, this code should be fairly efficient and
		// may be a good base for further optimizations anyway.
		//
		// Parameter 'val' to be encoded may be 0 or 1 (binary decision).
		//
		// Note: I've added full "Pacman" termination support to the
		// byte output routines, which is equivalent to the optional
		// Discard_final_zeros procedure (Figure D.15) in the spec.
		// Thus, we always produce the shortest possible output
		// stream compliant to the spec (no trailing zero bytes,
		// except for FF stuffing).
		//
		// I've also introduced a new scheme for accessing
		// the probability estimation state machine table,
		// derived from Markus Kuhn's JBIG implementation.
		static void arith_encode(jpeg_compress cinfo, ref byte st, int val)
		{
			arith_entropy_encoder e=(arith_entropy_encoder)cinfo.coef;

			// Fetch values from our compact representation of Table D.2:
			// Qe values and probability estimation state machine
			int sv=st;
			int qe=jaritab[sv&0x7F];			// => Qe_Value
			byte nl=(byte)(qe&0xFF); qe>>=8;	// Next_Index_LPS + Switch_MPS
			byte nm=(byte)(qe&0xFF); qe>>=8;	// Next_Index_MPS

			// Encode & estimation procedures per sections D.1.4 & D.1.5
			e.a-=qe;
			if(val!=(sv>>7))
			{
				// Encode the less probable symbol
				if(e.a>=qe)
				{
					// If the interval size (qe) for the less probable symbol (LPS)
					// is larger than the interval size for the MPS, then exchange
					// the two symbols for coding efficiency, otherwise code the LPS
					// as usual:
					e.c+=e.a;
					e.a=qe;
				}
				st=(byte)((sv&0x80)^nl);	// Estimate_after_LPS
			}
			else
			{
				// Encode the more probable symbol
				if(e.a>=0x8000) return;	// A >= 0x8000 -> ready, no renormalization required
				if(e.a<qe)
				{
					// If the interval size (qe) for the less probable symbol (LPS)
					// is larger than the interval size for the MPS, then exchange
					// the two symbols for coding efficiency:
					e.c+=e.a;
					e.a=qe;
				}
				st=(byte)((sv&0x80)^nm);	// Estimate_after_MPS
			}

			// Renormalization & data output per section D.1.6
			do
			{
				e.a<<=1;
				e.c<<=1;
				e.ct--;
				if(e.ct==0)
				{
					// Another byte is ready for output
					int temp=e.c>>19;
					if(temp>0xFF)
					{
						// Handle overflow over all stacked 0xFF bytes
						if(e.buffer>=0)
						{
							if(e.zc!=0)
							{
								do emit_byte(cinfo, 0x00);
								while((--e.zc)!=0);
							}
							emit_byte(cinfo, e.buffer+1);
							if(e.buffer+1==0xFF) emit_byte(cinfo, 0x00);
						}
						e.zc+=e.sc;	// carry-over converts stacked 0xFF bytes to 0x00
						e.sc=0;
						// Note: The 3 spacer bits in the C register guarantee
						// that the new buffer byte can't be 0xFF here
						// (see page 160 in the P&M JPEG book).
						e.buffer=temp&0xFF;	// new output byte, might overflow later
					}
					else if(temp==0xFF)
					{
						e.sc++;	// stack 0xFF byte (which might overflow later)
					}
					else
					{
						// Output all stacked 0xFF bytes, they will not overflow any more
						if(e.buffer==0) e.zc++;
						else if(e.buffer>=0)
						{
							if(e.zc!=0)
							{
								do emit_byte(cinfo, 0x00);
								while((--e.zc)!=0);
							}
							emit_byte(cinfo, e.buffer);
						}
						if(e.sc!=0)
						{
							if(e.zc!=0)
							{
								do emit_byte(cinfo, 0x00);
								while((--e.zc)!=0);
							}
							do
							{
								emit_byte(cinfo, 0xFF);
								emit_byte(cinfo, 0x00);
							} while((--e.sc)!=0);
						}
						e.buffer=temp&0xFF;	// new output byte (can still overflow)
					}
					e.c&=0x7FFFF;
					e.ct+=8;
				}
			} while(e.a<0x8000);
		}
Example #46
0
		// Module initialization routine for progressive Huffman entropy encoding.
		static void jinit_phuff_encoder(jpeg_compress cinfo)
		{
			jpeg_lossy_c_codec lossyc=(jpeg_lossy_c_codec)cinfo.coef;
			phuff_entropy_encoder entropy=null;

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

			lossyc.entropy_private=entropy;
			lossyc.entropy_start_pass=start_pass_phuff;
			lossyc.need_optimization_pass=need_optimization_pass_phuff;

			// Mark tables unallocated
			for(int i=0; i<NUM_HUFF_TBLS; i++)
			{
				entropy.derived_tbls[i]=null;
				entropy.count_ptrs[i]=null;
			}
			entropy.bit_buffer=null; // needed only in AC refinement scan
		}
Example #47
0
		// MCU encoding for DC initial scan (either spectral selection,
		// or first pass of successive approximation).
		static bool encode_mcu_DC_first_arith(jpeg_compress cinfo, short[][] MCU_data)
		{
			arith_entropy_encoder entropy=(arith_entropy_encoder)cinfo.coef;

			// Emit restart marker if needed
			if(cinfo.restart_interval!=0)
			{
				if(entropy.restarts_to_go==0)
				{
					emit_restart_arith(cinfo, entropy.next_restart_num);
					entropy.restarts_to_go=cinfo.restart_interval;
					entropy.next_restart_num++;
					entropy.next_restart_num&=7;
				}
				entropy.restarts_to_go--;
			}

			// Encode the MCU data blocks
			for(int blkn=0; blkn<cinfo.block_in_MCU; blkn++)
			{
				short[] block=MCU_data[blkn];
				int ci=cinfo.MCU_membership[blkn];
				int tbl=cinfo.cur_comp_info[ci].dc_tbl_no;

				// Compute the DC value after the required point transform by Al.
				// This is simply an arithmetic right shift.
				int m=(int)(block[0])>>cinfo.Al;

				// Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients

				// Table F.4: Point to statistics bin S0 for DC coefficient coding
				byte[] st=entropy.dc_stats[tbl];
				int st_ind=entropy.dc_context[ci];

				// Figure F.4: Encode_DC_DIFF
				int v=m-entropy.last_dc_val[ci];
				if(v==0)
				{
					arith_encode(cinfo, ref st[st_ind], 0);
					entropy.dc_context[ci]=0;	// zero diff category
				}
				else
				{
					entropy.last_dc_val[ci]=m;
					arith_encode(cinfo, ref st[st_ind], 1);

					// Figure F.6: Encoding nonzero value v
					// Figure F.7: Encoding the sign of v
					if(v>0)
					{
						arith_encode(cinfo, ref st[st_ind+1], 0);	// Table F.4: SS = S0 + 1
						st_ind+=2;									// Table F.4: SP = S0 + 2
						entropy.dc_context[ci]=4;					// small positive diff category
					}
					else
					{
						v=-v;
						arith_encode(cinfo, ref st[st_ind+1], 1);	// Table F.4: SS = S0 + 1
						st_ind+=3;									// Table F.4: SN = S0 + 3
						entropy.dc_context[ci]=8;					// small negative diff category
					}

					// Figure F.8: Encoding the magnitude category of v
					m=0;
					v--;
					if(v!=0)
					{
						arith_encode(cinfo, ref st[st_ind], 1);
						m=1;
						int v2=v;
						st=entropy.dc_stats[tbl];
						st_ind=20;					// Table F.4: X1 = 20
						while((v2>>=1)!=0)
						{
							arith_encode(cinfo, ref st[st_ind], 1);
							m<<=1;
							st_ind+=1;
						}
					}
					arith_encode(cinfo, ref st[st_ind], 0);

					// Section F.1.4.4.1.2: Establish dc_context conditioning category
					if(m<(int)((1<<cinfo.arith_dc_L[tbl])>>1)) entropy.dc_context[ci]=0;		// zero diff category
					else if(m>(int)((1<<cinfo.arith_dc_U[tbl])>>1)) entropy.dc_context[ci]+=8;	// large diff category

					// Figure F.9: Encoding the magnitude bit pattern of v
					st_ind+=14;
					while((m>>=1)!=0) arith_encode(cinfo, ref st[st_ind], ((m&v)!=0)?1:0);
				}
			}

			return true;
		}
Example #48
0
		static bool need_optimization_pass_phuff(jpeg_compress cinfo)
		{
			return (cinfo.Ss!=0||cinfo.Ah==0);
		}
Example #49
0
		// MCU encoding for DC successive approximation refinement scan.
		static bool encode_mcu_DC_refine_arith(jpeg_compress cinfo, short[][] MCU_data)
		{
			arith_entropy_encoder entropy=(arith_entropy_encoder)cinfo.coef;

			// Emit restart marker if needed
			if(cinfo.restart_interval!=0)
			{
				if(entropy.restarts_to_go==0)
				{
					emit_restart_arith(cinfo, entropy.next_restart_num);
					entropy.restarts_to_go=cinfo.restart_interval;
					entropy.next_restart_num++;
					entropy.next_restart_num&=7;
				}
				entropy.restarts_to_go--;
			}

			int Al=cinfo.Al;

			// Encode the MCU data blocks
			for(int blkn=0; blkn<cinfo.block_in_MCU; blkn++)
			{
				byte st=0;	// use fixed probability estimation
				// We simply emit the Al'th bit of the DC coefficient value.
				arith_encode(cinfo, ref st, (MCU_data[blkn][0]>>Al)&1);
			}

			return true;
		}
Example #50
0
		// Finish up a statistics-gathering pass and create the new Huffman tables.
		static void finish_pass_gather_phuff(jpeg_compress cinfo)
		{
			jpeg_lossy_c_codec lossyc=(jpeg_lossy_c_codec)cinfo.coef;
			phuff_entropy_encoder entropy=(phuff_entropy_encoder)lossyc.entropy_private;

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

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

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

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

				if(!did[tbl])
				{
					if(is_DC_band)
					{
						if(cinfo.dc_huff_tbl_ptrs[tbl]==null) cinfo.dc_huff_tbl_ptrs[tbl]=jpeg_alloc_huff_table(cinfo);
						jpeg_gen_optimal_table(cinfo, cinfo.dc_huff_tbl_ptrs[tbl], entropy.count_ptrs[tbl]);
					}
					else
					{
						if(cinfo.ac_huff_tbl_ptrs[tbl]==null) cinfo.ac_huff_tbl_ptrs[tbl]=jpeg_alloc_huff_table(cinfo);
						jpeg_gen_optimal_table(cinfo, cinfo.ac_huff_tbl_ptrs[tbl], entropy.count_ptrs[tbl]);
					}
					did[tbl]=true;
				}
			}
		}
Example #51
0
		// Encode and output one MCU's worth of arithmetic-compressed coefficients.
		static bool encode_mcu_arith(jpeg_compress cinfo, short[][] MCU_data)
		{
			arith_entropy_encoder entropy=(arith_entropy_encoder)cinfo.coef;

			// Emit restart marker if needed
			if(cinfo.restart_interval!=0)
			{
				if(entropy.restarts_to_go==0)
				{
					emit_restart_arith(cinfo, entropy.next_restart_num);
					entropy.restarts_to_go=cinfo.restart_interval;
					entropy.next_restart_num++;
					entropy.next_restart_num&=7;
				}
				entropy.restarts_to_go--;
			}

			// Encode the MCU data blocks
			for(int blkn=0; blkn<cinfo.block_in_MCU; blkn++)
			{
				short[] block=MCU_data[blkn];
				int ci=cinfo.MCU_membership[blkn];
				jpeg_component_info compptr=cinfo.cur_comp_info[ci];

				// Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients
				int tbl=compptr.dc_tbl_no;

				// Table F.4: Point to statistics bin S0 for DC coefficient coding
				byte[] st=entropy.dc_stats[tbl];
				int st_ind=entropy.dc_context[ci];

				// Figure F.4: Encode_DC_DIFF
				int v=block[0]-entropy.last_dc_val[ci];
				if(v==0)
				{
					arith_encode(cinfo, ref st[st_ind], 0);
					entropy.dc_context[ci]=0;	// zero diff category
				}
				else
				{
					entropy.last_dc_val[ci]=block[0];
					arith_encode(cinfo, ref st[st_ind], 1);

					// Figure F.6: Encoding nonzero value v
					// Figure F.7: Encoding the sign of v
					if(v>0)
					{
						arith_encode(cinfo, ref st[st_ind+1], 0);	// Table F.4: SS = S0 + 1
						st_ind+=2;									// Table F.4: SP = S0 + 2
						entropy.dc_context[ci]=4;					// small positive diff category
					}
					else
					{
						v=-v;
						arith_encode(cinfo, ref st[st_ind+1], 1);	//Table F.4: SS = S0 + 1
						st_ind+=3;									// Table F.4: SN = S0 + 3
						entropy.dc_context[ci]=8;					// small negative diff category
					}

					// Figure F.8: Encoding the magnitude category of v
					int m=0;
					v--;
					if(v!=0)
					{
						arith_encode(cinfo, ref st[st_ind], 1);
						m=1;
						int v2=v;
						st=entropy.dc_stats[tbl];
						st_ind=20; // Table F.4: X1 = 20
						while((v2>>=1)!=0)
						{
							arith_encode(cinfo, ref st[st_ind], 1);
							m<<=1;
							st_ind+=1;
						}
					}
					arith_encode(cinfo, ref st[st_ind], 0);

					// Section F.1.4.4.1.2: Establish dc_context conditioning category
					if(m<(int)((1<<cinfo.arith_dc_L[tbl])>>1)) entropy.dc_context[ci]=0;		// zero diff category
					else if(m>(int)((1<<cinfo.arith_dc_U[tbl])>>1)) entropy.dc_context[ci]+=8;	// large diff category

					// Figure F.9: Encoding the magnitude bit pattern of v
					st_ind+=14;
					while((m>>=1)!=0) arith_encode(cinfo, ref st[st_ind], ((m&v)!=0)?1:0);
				}

				// Sections F.1.4.2 & F.1.4.4.2: Encoding of AC coefficients
				tbl=compptr.ac_tbl_no;

				int k, ke;
				// Establish EOB (end-of-block) index
				for(ke=DCTSIZE2; ke>1; ke--)
				{
					if(block[jpeg_natural_order[ke-1]]!=0) break;
				}

				// Figure F.5: Encode_AC_Coefficients
				for(k=1; k<ke; k++)
				{
					st=entropy.ac_stats[tbl];
					st_ind=3*(k-1);
					arith_encode(cinfo, ref st[st_ind], 0);	// EOB decision
					while((v=block[jpeg_natural_order[k]])==0)
					{
						arith_encode(cinfo, ref st[st_ind+1], 0); st_ind+=3; k++;
					}
					arith_encode(cinfo, ref st[st_ind+1], 1);

					// Figure F.6: Encoding nonzero value v
					// Figure F.7: Encoding the sign of v
					entropy.ac_stats[tbl][245]=0;
					if(v>0)
					{
						arith_encode(cinfo, ref entropy.ac_stats[tbl][245], 0);
					}
					else
					{
						v=-v;
						arith_encode(cinfo, ref entropy.ac_stats[tbl][245], 1);
					}
					st_ind+=2;

					// Figure F.8: Encoding the magnitude category of v
					int m=0;
					v--;
					if(v!=0)
					{
						arith_encode(cinfo, ref st[st_ind], 1);
						m=1;
						int v2=v;
						v2>>=1;
						if(v2!=0)
						{
							arith_encode(cinfo, ref st[st_ind], 1);
							m<<=1;
							st=entropy.ac_stats[tbl];
							st_ind=(k<=cinfo.arith_ac_K[tbl]?189:217);
							while((v2>>=1)!=0)
							{
								arith_encode(cinfo, ref st[st_ind], 1);
								m<<=1;
								st_ind+=1;
							}
						}
					}
					arith_encode(cinfo, ref st[st_ind], 0);

					// Figure F.9: Encoding the magnitude bit pattern of v
					st_ind+=14;
					while((m>>=1)!=0) arith_encode(cinfo, ref st[st_ind], ((m&v)!=0)?1:0);
				}

				// Encode EOB decision only if k < DCTSIZE2
				if(k<DCTSIZE2)
				{
					st=entropy.ac_stats[tbl];
					st_ind=3*(k-1);
					arith_encode(cinfo, ref st[st_ind], 1);
				}
			}

			return true;
		}
Example #52
0
 // Empty method for start_pass.
 static void null_method(jpeg_compress cinfo)
 {
     // no work needed
 }
Example #53
0
		// Initialize for an arithmetic-compressed scan.
		static void start_pass_c_arith(jpeg_compress cinfo, bool gather_statistics)
		{
			arith_entropy_encoder entropy=(arith_entropy_encoder)cinfo.coef;

			if(gather_statistics)
			{
				// Make sure to avoid that in the master control logic!
				// We are fully adaptive here and need no extra
				// statistics gathering pass!
				ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOT_COMPILED);
			}

			// We assume jcmaster.cs already validated the progressive scan parameters.

			// Select execution routines
			if(cinfo.process==J_CODEC_PROCESS.JPROC_PROGRESSIVE)
			{
				if(cinfo.Ah==0)
				{
					if(cinfo.Ss==0) entropy.entropy_encode_mcu=encode_mcu_DC_first_arith;
					else entropy.entropy_encode_mcu=encode_mcu_AC_first_arith;
				}
				else
				{
					if(cinfo.Ss==0) entropy.entropy_encode_mcu=encode_mcu_DC_refine_arith;
					else entropy.entropy_encode_mcu=encode_mcu_AC_refine_arith;
				}
			}
			else if(cinfo.process==J_CODEC_PROCESS.JPROC_SEQUENTIAL) entropy.entropy_encode_mcu=encode_mcu_arith;
			else ERREXIT(cinfo, J_MESSAGE_CODE.JERR_NOTIMPL);

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

				// Allocate & initialize requested statistics areas
				if(cinfo.process!=J_CODEC_PROCESS.JPROC_PROGRESSIVE||(cinfo.Ss==0&&cinfo.Ah==0))
				{
					int tbl=compptr.dc_tbl_no;
					if(tbl<0||tbl>=NUM_ARITH_TBLS) ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_NO_ARITH_TABLE, tbl);
					if(entropy.dc_stats[tbl]==null)
					{
						try
						{
							entropy.dc_stats[tbl]=new byte[DC_STAT_BINS];
						}
						catch
						{
							ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
						}
					}
					else
					{
						for(int i=0; i<DC_STAT_BINS; i++) entropy.dc_stats[tbl][i]=0;
					}
					// Initialize DC predictions to 0
					entropy.last_dc_val[ci]=0;
					entropy.dc_context[ci]=0;
				}
				if(cinfo.process!=J_CODEC_PROCESS.JPROC_PROGRESSIVE||cinfo.Ss!=0)
				{
					int tbl=compptr.ac_tbl_no;
					if(tbl<0||tbl>=NUM_ARITH_TBLS) ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_NO_ARITH_TABLE, tbl);
					if(entropy.ac_stats[tbl]==null)
					{
						try
						{
							entropy.ac_stats[tbl]=new byte[AC_STAT_BINS];
						}
						catch
						{
							ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
						}
					}
					else
					{
						for(int i=0; i<AC_STAT_BINS; i++) entropy.ac_stats[tbl][i]=0;
					}

#if CALCULATE_SPECTRAL_CONDITIONING
					if(cinfo.process==J_CODEC_PROCESS.JPROC_PROGRESSIVE)
					{
						// Section G.1.3.2: Set appropriate arithmetic conditioning value Kx
						cinfo.arith_ac_K[tbl]=(byte)(cinfo.Ss+((8+cinfo.Se-cinfo.Ss)>>4));
					}
#endif
				}
			}

			// Initialize arithmetic encoding variables
			entropy.c=0;
			entropy.a=0x10000;
			entropy.sc=0;
			entropy.zc=0;
			entropy.ct=11;
			entropy.buffer=-1;	// empty

			// Initialize restart stuff
			entropy.restarts_to_go=cinfo.restart_interval;
			entropy.next_restart_num=0;
		}
Example #54
0
        // Module initialization routine for input colorspace conversion.
        static void jinit_color_converter(jpeg_compress cinfo)
        {
            my_color_converter cconvert = null;

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

            // set start_pass to null method until we find out differently
            cconvert.start_pass = null_method;

            // Make sure input_components agrees with in_color_space
            switch (cinfo.in_color_space)
            {
            case J_COLOR_SPACE.JCS_GRAYSCALE:
                if (cinfo.input_components != 1)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_IN_COLORSPACE);
                }
                break;

            case J_COLOR_SPACE.JCS_RGB:
            case J_COLOR_SPACE.JCS_YCbCr:
                if (cinfo.input_components != 3)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_IN_COLORSPACE);
                }
                break;

            case J_COLOR_SPACE.JCS_CMYK:
            case J_COLOR_SPACE.JCS_YCCK:
                if (cinfo.input_components != 4)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_IN_COLORSPACE);
                }
                break;

            default:                     // JCS_UNKNOWN can be anything
                if (cinfo.input_components < 1)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_IN_COLORSPACE);
                }
                break;
            }

            // Check num_components, set conversion method based on requested space
            switch (cinfo.jpeg_color_space)
            {
            case J_COLOR_SPACE.JCS_GRAYSCALE:
                if (cinfo.num_components != 1)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                }
                if (cinfo.in_color_space == J_COLOR_SPACE.JCS_GRAYSCALE)
                {
                    cconvert.color_convert = grayscale_convert;
                }
                else if (cinfo.in_color_space == J_COLOR_SPACE.JCS_RGB)
                {
                    cconvert.start_pass    = rgb_ycc_start;
                    cconvert.color_convert = rgb_gray_convert;
                }
                else if (cinfo.in_color_space == J_COLOR_SPACE.JCS_YCbCr)
                {
                    cconvert.color_convert = grayscale_convert;
                }
                else
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                }
                break;

            case J_COLOR_SPACE.JCS_RGB:
                if (cinfo.num_components != 3)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                }
                if (cinfo.in_color_space == J_COLOR_SPACE.JCS_RGB && RGB_PIXELSIZE == 3)
                {
                    cconvert.color_convert = null_convert;
                }
                else
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                }
                break;

            case J_COLOR_SPACE.JCS_YCbCr:
                if (cinfo.num_components != 3)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                }
                if (cinfo.in_color_space == J_COLOR_SPACE.JCS_RGB)
                {
                    cconvert.start_pass    = rgb_ycc_start;
                    cconvert.color_convert = rgb_ycc_convert;
                }
                else if (cinfo.in_color_space == J_COLOR_SPACE.JCS_YCbCr)
                {
                    cconvert.color_convert = null_convert;
                }
                else
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                }
                break;

            case J_COLOR_SPACE.JCS_CMYK:
                if (cinfo.num_components != 4)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                }
                if (cinfo.in_color_space == J_COLOR_SPACE.JCS_CMYK)
                {
                    cconvert.color_convert = null_convert;
                }
                else
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                }
                break;

            case J_COLOR_SPACE.JCS_YCCK:
                if (cinfo.num_components != 4)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_J_COLORSPACE);
                }
                if (cinfo.in_color_space == J_COLOR_SPACE.JCS_CMYK)
                {
                    cconvert.start_pass    = rgb_ycc_start;
                    cconvert.color_convert = cmyk_ycck_convert;
                }
                else if (cinfo.in_color_space == J_COLOR_SPACE.JCS_YCCK)
                {
                    cconvert.color_convert = null_convert;
                }
                else
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                }
                break;

            default:                     // allow null conversion of JCS_UNKNOWN
                if (cinfo.jpeg_color_space != cinfo.in_color_space ||
                    cinfo.num_components != cinfo.input_components)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_CONVERSION_NOTIMPL);
                }
                cconvert.color_convert = null_convert;
                break;
            }
        }
Example #55
0
        // MCU encoding for DC initial scan (either spectral selection,
        // or first pass of successive approximation).
        static bool encode_mcu_DC_first_phuff(jpeg_compress cinfo, short[][] MCU_data)
        {
            jpeg_lossy_c_codec    lossyc  = (jpeg_lossy_c_codec)cinfo.coef;
            phuff_entropy_encoder entropy = (phuff_entropy_encoder)lossyc.entropy_private;
            int Al = cinfo.Al;

            entropy.output_bytes     = cinfo.dest.output_bytes;
            entropy.next_output_byte = cinfo.dest.next_output_byte;
            entropy.free_in_buffer   = cinfo.dest.free_in_buffer;

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

            // Encode the MCU data blocks
            for (int blkn = 0; blkn < cinfo.block_in_MCU; blkn++)
            {
                short[]             block   = MCU_data[blkn];
                int                 ci      = cinfo.MCU_membership[blkn];
                jpeg_component_info compptr = cinfo.cur_comp_info[ci];

                // Compute the DC value after the required point transform by Al.
                // This is simply an arithmetic right shift.
                int temp2 = (int)block[0] >> Al;

                // DC differences are figured on the point-transformed values.
                int temp = temp2 - entropy.last_dc_val[ci];
                entropy.last_dc_val[ci] = temp2;

                // Encode the DC coefficient difference per section G.1.2.1
                temp2 = temp;
                if (temp < 0)
                {
                    temp = -temp;                   // temp is abs value of input
                    // For a negative input, want temp2 = bitwise complement of abs(input)
                    // This code assumes we are on a two's complement machine
                    temp2--;
                }

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

                // Check for out-of-range coefficient values.
                // Since we're encoding a difference, the range limit is twice as much.
                if (nbits > MAX_COEF_BITS + 1)
                {
                    ERREXIT(cinfo, J_MESSAGE_CODE.JERR_BAD_DCT_COEF);
                }

                // Count/emit the Huffman-coded symbol for the number of bits
                emit_symbol(entropy, compptr.dc_tbl_no, nbits);

                // Emit that number of bits of the value, if positive,
                // or the complement of its magnitude, if negative.
                if (nbits != 0)
                {
                    emit_bits(entropy, (uint)temp2, nbits);                          // emit_bits rejects calls with size 0
                }
            }

            cinfo.dest.output_bytes     = entropy.output_bytes;
            cinfo.dest.next_output_byte = entropy.next_output_byte;
            cinfo.dest.free_in_buffer   = entropy.free_in_buffer;

            // 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(true);
        }
Example #56
0
		// Write datastream trailer.
		static void write_file_trailer(jpeg_compress cinfo)
		{
			emit_marker(cinfo, JPEG_MARKER.M_EOI);
		}
Example #57
0
        const int MAX_CORR_BITS = 1000;         // Max # of correction bits I can buffer

        // Initialize for a Huffman-compressed scan using progressive JPEG.
        static void start_pass_phuff(jpeg_compress cinfo, bool gather_statistics)
        {
            jpeg_lossy_c_codec    lossyc  = (jpeg_lossy_c_codec)cinfo.coef;
            phuff_entropy_encoder entropy = (phuff_entropy_encoder)lossyc.entropy_private;

            entropy.cinfo             = cinfo;
            entropy.gather_statistics = gather_statistics;

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

            // We assume jcmaster.cs already validated the scan parameters.
            // Select execution routines
            if (cinfo.Ah == 0)
            {
                if (is_DC_band)
                {
                    lossyc.entropy_encode_mcu = encode_mcu_DC_first_phuff;
                }
                else
                {
                    lossyc.entropy_encode_mcu = encode_mcu_AC_first_phuff;
                }
            }
            else
            {
                if (is_DC_band)
                {
                    lossyc.entropy_encode_mcu = encode_mcu_DC_refine_phuff;
                }
                else
                {
                    lossyc.entropy_encode_mcu = encode_mcu_AC_refine_phuff;
                    // AC refinement needs a correction bit buffer
                    if (entropy.bit_buffer == null)
                    {
                        try
                        {
                            entropy.bit_buffer = new byte[MAX_CORR_BITS];
                        }
                        catch
                        {
                            ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_OUT_OF_MEMORY, 4);
                        }
                    }
                }
            }

            if (gather_statistics)
            {
                lossyc.entropy_finish_pass = finish_pass_gather_phuff;
            }
            else
            {
                lossyc.entropy_finish_pass = finish_pass_phuff;
            }

            // Only DC coefficients may be interleaved, so cinfo.comps_in_scan = 1
            // for AC coefficients.
            for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
            {
                jpeg_component_info compptr = cinfo.cur_comp_info[ci];

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

                // Get table index
                int tbl;
                if (is_DC_band)
                {
                    if (cinfo.Ah != 0)
                    {
                        continue;                                 // DC refinement needs no table
                    }
                    tbl = compptr.dc_tbl_no;
                }
                else
                {
                    entropy.ac_tbl_no = tbl = compptr.ac_tbl_no;
                }

                if (gather_statistics)
                {
                    // Check for invalid table index
                    // (make_c_derived_tbl does this in the other path)
                    if (tbl < 0 || tbl >= NUM_HUFF_TBLS)
                    {
                        ERREXIT1(cinfo, J_MESSAGE_CODE.JERR_NO_HUFF_TABLE, tbl);
                    }

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

            // Initialize AC stuff
            entropy.EOBRUN = 0;
            entropy.BE     = 0;

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

            // Initialize restart stuff
            entropy.restarts_to_go   = cinfo.restart_interval;
            entropy.next_restart_num = 0;
        }
Example #58
0
		// Convert some rows of samples to the JPEG colorspace.
		// This version handles grayscale output with no conversion.
		// The source can be either plain grayscale or YCbCr (since Y == gray).
		static void grayscale_convert(jpeg_compress cinfo, byte[][] input_buf, uint in_row_index, byte[][][] output_buf, uint output_row, int num_rows)
		{
			uint num_cols=cinfo.image_width;
			int instride=cinfo.input_components;

			for(uint input_row=0; input_row<num_rows; input_row++)
			{
				byte[] inptr=input_buf[in_row_index+input_row];
				byte[] outptr=output_buf[0][output_row];
				output_row++;
				for(uint col=0, off=0; col<num_cols; col++, off+=(uint)instride) outptr[col]=inptr[off];
			}
		}
Example #59
0
 static bool need_optimization_pass_phuff(jpeg_compress cinfo)
 {
     return(cinfo.Ss != 0 || cinfo.Ah == 0);
 }
Example #60
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);
        }