/// <summary>
        /// Alternate compression function: just write an abbreviated table file.
        /// </summary>
        /// <remarks>Before calling this, all parameters and a data destination must be set up.<br/>
        /// 
        /// To produce a pair of files containing abbreviated tables and abbreviated
        /// image data, one would proceed as follows:<br/>
        /// 
        /// <c>Initialize JPEG object<br/>
        /// Set JPEG parameters<br/>
        /// Set destination to table file<br/>
        /// <see cref="jpeg_compress_struct.jpeg_write_tables">jpeg_write_tables();</see><br/>
        /// Set destination to image file<br/>
        /// <see cref="jpeg_compress_struct.jpeg_start_compress">jpeg_start_compress(false);</see><br/>
        /// Write data...<br/>
        /// <see cref="jpeg_compress_struct.jpeg_finish_compress">jpeg_finish_compress();</see><br/>
        /// </c><br/>
        /// 
        /// jpeg_write_tables has the side effect of marking all tables written
        /// (same as <see cref="jpeg_compress_struct.jpeg_suppress_tables">jpeg_suppress_tables(true)</see>).
        /// Thus a subsequent <see cref="jpeg_compress_struct.jpeg_start_compress">jpeg_start_compress</see> 
        /// will not re-emit the tables unless it is passed <c>write_all_tables=true</c>.
        /// </remarks>
        public void jpeg_write_tables()
        {
            if (m_global_state != JpegState.CSTATE_START)
                ERREXIT(J_MESSAGE_CODE.JERR_BAD_STATE, (int)m_global_state);

            /* (Re)initialize error mgr and destination modules */
            m_err.reset_error_mgr();
            m_dest.init_destination();

            /* Initialize the marker writer ... bit of a crock to do it here. */
            m_marker = new jpeg_marker_writer(this);

            /* Write them tables! */
            m_marker.write_tables_only();

            /* And clean up. */
            m_dest.term_destination();
        }
        /// <summary>
        /// Master selection of compression modules for transcoding.
        /// </summary>
        private void transencode_master_selection(jvirt_array<JBLOCK>[] coef_arrays)
        {
            /* Although we don't actually use input_components for transcoding, 
             * jcmaster.c's initial_setup will complain if input_components is 0.
             */
            m_input_components = 1;

            /* Initialize master control (includes parameter checking/processing) */
            jinit_c_master_control(true /* transcode only */);

            /* Entropy encoding: only Huffman coding supported. */
            if (m_progressive_mode)
                m_entropy = new phuff_entropy_encoder(this);
            else
                m_entropy = new huff_entropy_encoder(this);

            /* We need a special coefficient buffer controller. */
            m_coef = new my_trans_c_coef_controller(this, coef_arrays);
            m_marker = new jpeg_marker_writer(this);

            /* Write the datastream header (SOI, JFIF) immediately.
            * Frame and scan headers are postponed till later.
            * This lets application insert special markers after the SOI.
            */
            m_marker.write_file_header();
        }
        /// <summary>
        /// Master selection of compression modules for transcoding.
        /// </summary>
        private void transencode_master_selection(jvirt_array<JBLOCK>[] coef_arrays)
        {
            /* Initialize master control (includes parameter checking/processing) */
            jinit_c_master_control(true /* transcode only */);

            /* Entropy encoding: only Huffman or arithmetic coding. */
            if (arith_code)
                m_entropy = new arith_entropy_encoder(this);
            else
                m_entropy = new huff_entropy_encoder(this);

            /* We need a special coefficient buffer controller. */
            m_coef = new my_trans_c_coef_controller(this, coef_arrays);
            m_marker = new jpeg_marker_writer(this);

            /* Write the datastream header (SOI, JFIF) immediately.
            * Frame and scan headers are postponed till later.
            * This lets application insert special markers after the SOI.
            */
            m_marker.write_file_header();
        }
        /// <summary>
        /// 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.
        /// This routine is in charge of selecting the modules to be executed and
        /// making an initialization call to each one.
        /// </summary>
        private void jinit_compress_master()
        {
            /* Initialize master control (includes parameter checking/processing) */
            jinit_c_master_control(false /* full compression */);

            /* Preprocessing */
            if (!m_raw_data_in)
            {
                m_cconvert = new jpeg_color_converter(this);
                m_downsample = new jpeg_downsampler(this);
                m_prep = new jpeg_c_prep_controller(this);
            }

            /* Forward DCT */
            m_fdct = new jpeg_forward_dct(this);

            /* Entropy encoding: only Huffman coding supported. */
            if (m_progressive_mode)
                m_entropy = new phuff_entropy_encoder(this);
            else
                m_entropy = new huff_entropy_encoder(this);

            /* Need a full-image coefficient buffer in any multi-pass mode. */
            m_coef = new my_c_coef_controller(this, (bool)(m_num_scans > 1 || m_optimize_coding));
            jinit_c_main_controller(false /* never need full buffer here */);
            m_marker = new jpeg_marker_writer(this);

            /* Write the datastream header (SOI) immediately.
            * Frame and scan headers are postponed till later.
            * This lets application insert special markers after the SOI.
            */
            m_marker.write_file_header();
        }
        /// <summary>
        /// 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.
        /// This routine is in charge of selecting the modules to be executed and
        /// making an initialization call to each one.
        /// </summary>
        private void jinit_compress_master()
        {
            /* Sanity check on image dimensions */
            if (m_image_height <= 0 || m_image_width <= 0 || m_input_components <= 0)
                ERREXIT(J_MESSAGE_CODE.JERR_EMPTY_IMAGE);

            /* Initialize master control (includes parameter checking/processing) */
            jinit_c_master_control(false /* full compression */);

            /* Preprocessing */
            if (!m_raw_data_in)
            {
                m_cconvert = new jpeg_color_converter(this);
                m_downsample = new jpeg_downsampler(this);
                m_prep = new jpeg_c_prep_controller(this);
            }

            /* Forward DCT */
            m_fdct = new jpeg_forward_dct(this);

            /* Entropy encoding: either Huffman or arithmetic coding. */
            if (arith_code)
                m_entropy = new arith_entropy_encoder(this);
            else
                m_entropy = new huff_entropy_encoder(this);

            /* Need a full-image coefficient buffer in any multi-pass mode. */
            m_coef = new my_c_coef_controller(this, (bool)(m_num_scans > 1 || m_optimize_coding));
            jinit_c_main_controller(false /* never need full buffer here */);
            m_marker = new jpeg_marker_writer(this);

            /* Write the datastream header (SOI) immediately.
            * Frame and scan headers are postponed till later.
            * This lets application insert special markers after the SOI.
            */
            m_marker.write_file_header();
        }