Compression preprocessing (downsampling input buffer control). For the simple (no-context-row) case, we just need to buffer one row group's worth of pixels for the downsampling step. At the bottom of the image, we pad to a full row group by replicating the last pixel row. The downsampler's last output row is then replicated if needed to pad out to a full iMCU row. When providing context rows, we must buffer three row groups' worth of pixels. Three row groups are physically allocated, but the row pointer arrays are made five row groups high, with the extra pointers above and below "wrapping around" to point to the last and first real row groups. This allows the downsampler to access the proper context rows. At the top and bottom of the image, we create dummy context rows by copying the first or last real pixel row. This copying could be avoided by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the trouble on the compression side.
        /// <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();
        }