BitMiracle.LibJpeg.Classic.Internal.jpeg_downsampler.h2v2_smooth_downsample C# (CSharp) Method

h2v2_smooth_downsample() private method

Downsample pixel values of a single component. This version handles the standard case of 2:1 horizontal and 2:1 vertical, with smoothing. One row of context is required.
private h2v2_smooth_downsample ( int componentIndex, byte input_data, int startInputRow, byte output_data, int startOutRow ) : void
componentIndex int
input_data byte
startInputRow int
output_data byte
startOutRow int
return void
        private void h2v2_smooth_downsample(int componentIndex, byte[][] input_data, int startInputRow, byte[][] output_data, int startOutRow)
        {
            /* Expand input data enough to let all the output samples be generated
             * by the standard loop.  Special-casing padded output would be more
             * efficient.
             */
            jpeg_component_info compptr = m_cinfo.Component_info[componentIndex];
            int output_cols = compptr.Width_in_blocks * compptr.DCT_h_scaled_size;
            expand_right_edge(input_data, startInputRow - 1, m_cinfo.m_max_v_samp_factor + 2, m_cinfo.m_image_width, output_cols * 2);

            /* We don't bother to form the individual "smoothed" input pixel values;
             * we can directly compute the output which is the average of the four
             * smoothed values.  Each of the four member pixels contributes a fraction
             * (1-8*SF) to its own smoothed image and a fraction SF to each of the three
             * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final
             * output.  The four corner-adjacent neighbor pixels contribute a fraction
             * SF to just one smoothed pixel, or SF/4 to the final output; while the
             * eight edge-adjacent neighbors contribute SF to each of two smoothed
             * pixels, or SF/2 overall.  In order to use integer arithmetic, these
             * factors are scaled by 2^16 = 65536.
             * Also recall that SF = smoothing_factor / 1024.
             */

            int memberscale = 16384 - m_cinfo.m_smoothing_factor * 80; /* scaled (1-5*SF)/4 */
            int neighscale = m_cinfo.m_smoothing_factor * 16; /* scaled SF/4 */

            int inrow = 0;
            int outrow = 0;
            while (inrow < m_cinfo.m_max_v_samp_factor)
            {
                int outIndex = 0;
                int inIndex0 = 0;
                int inIndex1 = 0;
                int aboveIndex = 0;
                int belowIndex = 0;

                /* Special case for first column: pretend column -1 is same as column 0 */
                int membersum = input_data[startInputRow + inrow][inIndex0] +
                    input_data[startInputRow + inrow][inIndex0 + 1] +
                    input_data[startInputRow + inrow + 1][inIndex1] +
                    input_data[startInputRow + inrow + 1][inIndex1 + 1];

                int neighsum = input_data[startInputRow + inrow - 1][aboveIndex] +
                    input_data[startInputRow + inrow - 1][aboveIndex + 1] +
                    input_data[startInputRow + inrow + 2][belowIndex] +
                    input_data[startInputRow + inrow + 2][belowIndex + 1] +
                    input_data[startInputRow + inrow][inIndex0] +
                    input_data[startInputRow + inrow][inIndex0 + 2] +
                    input_data[startInputRow + inrow + 1][inIndex1] +
                    input_data[startInputRow + inrow + 1][inIndex1 + 2];

                neighsum += neighsum;
                neighsum += input_data[startInputRow + inrow - 1][aboveIndex] +
                    input_data[startInputRow + inrow - 1][aboveIndex + 2] +
                    input_data[startInputRow + inrow + 2][belowIndex] +
                    input_data[startInputRow + inrow + 2][belowIndex + 2];

                membersum = membersum * memberscale + neighsum * neighscale;
                output_data[startOutRow + outrow][outIndex] = (byte)((membersum + 32768) >> 16);
                outIndex++;

                inIndex0 += 2;
                inIndex1 += 2;
                aboveIndex += 2;
                belowIndex += 2;

                for (int colctr = output_cols - 2; colctr > 0; colctr--)
                {
                    /* sum of pixels directly mapped to this output element */
                    membersum = input_data[startInputRow + inrow][inIndex0] +
                        input_data[startInputRow + inrow][inIndex0 + 1] +
                        input_data[startInputRow + inrow + 1][inIndex1] +
                        input_data[startInputRow + inrow + 1][inIndex1 + 1];

                    /* sum of edge-neighbor pixels */
                    neighsum = input_data[startInputRow + inrow - 1][aboveIndex] +
                        input_data[startInputRow + inrow - 1][aboveIndex + 1] +
                        input_data[startInputRow + inrow + 2][belowIndex] +
                        input_data[startInputRow + inrow + 2][belowIndex + 1] +
                        input_data[startInputRow + inrow][inIndex0 - 1] +
                        input_data[startInputRow + inrow][inIndex0 + 2] +
                        input_data[startInputRow + inrow + 1][inIndex1 - 1] +
                        input_data[startInputRow + inrow + 1][inIndex1 + 2];

                    /* The edge-neighbors count twice as much as corner-neighbors */
                    neighsum += neighsum;

                    /* Add in the corner-neighbors */
                    neighsum += input_data[startInputRow + inrow - 1][aboveIndex - 1] +
                        input_data[startInputRow + inrow - 1][aboveIndex + 2] +
                        input_data[startInputRow + inrow + 2][belowIndex - 1] +
                        input_data[startInputRow + inrow + 2][belowIndex + 2];

                    /* form final output scaled up by 2^16 */
                    membersum = membersum * memberscale + neighsum * neighscale;

                    /* round, descale and output it */
                    output_data[startOutRow + outrow][outIndex] = (byte)((membersum + 32768) >> 16);
                    outIndex++;

                    inIndex0 += 2;
                    inIndex1 += 2;
                    aboveIndex += 2;
                    belowIndex += 2;
                }

                /* Special case for last column */
                membersum = input_data[startInputRow + inrow][inIndex0] +
                    input_data[startInputRow + inrow][inIndex0 + 1] +
                    input_data[startInputRow + inrow + 1][inIndex1] +
                    input_data[startInputRow + inrow + 1][inIndex1 + 1];

                neighsum = input_data[startInputRow + inrow - 1][aboveIndex] +
                    input_data[startInputRow + inrow - 1][aboveIndex + 1] +
                    input_data[startInputRow + inrow + 2][belowIndex] +
                    input_data[startInputRow + inrow + 2][belowIndex + 1] +
                    input_data[startInputRow + inrow][inIndex0 - 1] +
                    input_data[startInputRow + inrow][inIndex0 + 1] +
                    input_data[startInputRow + inrow + 1][inIndex1 - 1] +
                    input_data[startInputRow + inrow + 1][inIndex1 + 1];

                neighsum += neighsum;
                neighsum += input_data[startInputRow + inrow - 1][aboveIndex - 1] +
                    input_data[startInputRow + inrow - 1][aboveIndex + 1] +
                    input_data[startInputRow + inrow + 2][belowIndex - 1] +
                    input_data[startInputRow + inrow + 2][belowIndex + 1];

                membersum = membersum * memberscale + neighsum * neighscale;
                output_data[startOutRow + outrow][outIndex] = (byte)((membersum + 32768) >> 16);

                inrow += 2;
                outrow++;
            }
        }