예제 #1
0
        /*
         * These are the routines invoked by the control routines to do
         * the actual upsampling/conversion.  One row group is processed per call.
         *
         * Note: since we may be writing directly into application-supplied buffers,
         * we have to be honest about the output width; we can't assume the buffer
         * has been rounded up to an even width.
         */

        /// <summary>
        /// Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical.
        /// </summary>
        private void h2v1_merged_upsample(ComponentBuffer[] input_buf, int in_row_group_ctr, byte[][] output_buf, int outRow)
        {
            int inputIndex0 = 0;
            int inputIndex1 = 0;
            int inputIndex2 = 0;
            int outputIndex = 0;

            byte[] limit       = m_cinfo.m_sample_range_limit;
            int    limitOffset = m_cinfo.m_sampleRangeLimitOffset;

            /* Loop for each pair of output pixels */
            for (int col = m_cinfo.m_output_width >> 1; col > 0; col--)
            {
                /* Do the chroma part of the calculation */
                int cb = input_buf[1][in_row_group_ctr][inputIndex1];
                inputIndex1++;

                int cr = input_buf[2][in_row_group_ctr][inputIndex2];
                inputIndex2++;

                int cred   = m_Cr_r_tab[cr];
                int cgreen = JpegUtils.RIGHT_SHIFT(m_Cb_g_tab[cb] + m_Cr_g_tab[cr], SCALEBITS);
                int cblue  = m_Cb_b_tab[cb];

                /* Fetch 2 Y values and emit 2 pixels */
                int y = input_buf[0][in_row_group_ctr][inputIndex0];
                inputIndex0++;

                output_buf[outRow][outputIndex + JpegConstants.RGB_RED]   = limit[limitOffset + y + cred];
                output_buf[outRow][outputIndex + JpegConstants.RGB_GREEN] = limit[limitOffset + y + cgreen];
                output_buf[outRow][outputIndex + JpegConstants.RGB_BLUE]  = limit[limitOffset + y + cblue];
                outputIndex += JpegConstants.RGB_PIXELSIZE;

                y = input_buf[0][in_row_group_ctr][inputIndex0];
                inputIndex0++;

                output_buf[outRow][outputIndex + JpegConstants.RGB_RED]   = limit[limitOffset + y + cred];
                output_buf[outRow][outputIndex + JpegConstants.RGB_GREEN] = limit[limitOffset + y + cgreen];
                output_buf[outRow][outputIndex + JpegConstants.RGB_BLUE]  = limit[limitOffset + y + cblue];
                outputIndex += JpegConstants.RGB_PIXELSIZE;
            }

            /* If image width is odd, do the last output column separately */
            if ((m_cinfo.m_output_width & 1) != 0)
            {
                int cb     = input_buf[1][in_row_group_ctr][inputIndex1];
                int cr     = input_buf[2][in_row_group_ctr][inputIndex2];
                int cred   = m_Cr_r_tab[cr];
                int cgreen = JpegUtils.RIGHT_SHIFT(m_Cb_g_tab[cb] + m_Cr_g_tab[cr], SCALEBITS);
                int cblue  = m_Cb_b_tab[cb];

                int y = input_buf[0][in_row_group_ctr][inputIndex0];
                output_buf[outRow][outputIndex + JpegConstants.RGB_RED]   = limit[limitOffset + y + cred];
                output_buf[outRow][outputIndex + JpegConstants.RGB_GREEN] = limit[limitOffset + y + cgreen];
                output_buf[outRow][outputIndex + JpegConstants.RGB_BLUE]  = limit[limitOffset + y + cblue];
            }
        }
예제 #2
0
        /// <summary>
        /// Adobe-style YCCK->CMYK conversion.
        /// We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
        /// conversion as above, while passing K (black) unchanged.
        /// We assume build_ycc_rgb_table has been called.
        /// </summary>
        private void YcckCmykConvert(ComponentBuffer[] input_buf, int input_row, byte[][] output_buf, int output_row, int num_rows)
        {
            var component0RowOffset = m_perComponentOffsets[0];
            var component1RowOffset = m_perComponentOffsets[1];
            var component2RowOffset = m_perComponentOffsets[2];
            var component3RowOffset = m_perComponentOffsets[3];

            var limit       = m_cinfo.m_sample_range_limit;
            var limitOffset = m_cinfo.m_sampleRangeLimitOffset;

            var num_cols = m_cinfo.outputWidth;

            for (var row = 0; row < num_rows; row++)
            {
                var columnOffset = 0;
                for (var col = 0; col < num_cols; col++)
                {
                    int y  = input_buf[0][input_row + component0RowOffset][col];
                    int cb = input_buf[1][input_row + component1RowOffset][col];
                    int cr = input_buf[2][input_row + component2RowOffset][col];

                    /* Range-limiting is essential due to noise introduced by DCT losses,
                     * and for extended gamut encodings (sYCC).
                     */
                    output_buf[output_row + row][columnOffset]     = limit[limitOffset + JpegConstants.MAXJSAMPLE - (y + m_Cr_r_tab[cr])];                                                    /* red */
                    output_buf[output_row + row][columnOffset + 1] = limit[limitOffset + JpegConstants.MAXJSAMPLE - (y + JpegUtils.RIGHT_SHIFT(m_Cb_g_tab[cb] + m_Cr_g_tab[cr], SCALEBITS))]; /* green */
                    output_buf[output_row + row][columnOffset + 2] = limit[limitOffset + JpegConstants.MAXJSAMPLE - (y + m_Cb_b_tab[cb])];                                                    /* blue */

                    /* K passes through unchanged */
                    /* don't need GETJSAMPLE here */
                    output_buf[output_row + row][columnOffset + 3] = input_buf[3][input_row + component3RowOffset][col];
                    columnOffset += 4;
                }

                input_row++;
            }
        }
예제 #3
0
        private void YccRgbConvert(ComponentBuffer[] input_buf, int input_row, byte[][] output_buf, int output_row, int num_rows)
        {
            var component0RowOffset = m_perComponentOffsets[0];
            var component1RowOffset = m_perComponentOffsets[1];
            var component2RowOffset = m_perComponentOffsets[2];

            var limit       = m_cinfo.m_sample_range_limit;
            var limitOffset = m_cinfo.m_sampleRangeLimitOffset;

            for (var row = 0; row < num_rows; row++)
            {
                var columnOffset = 0;
                for (var col = 0; col < m_cinfo.outputWidth; col++)
                {
                    int y  = input_buf[0][input_row + component0RowOffset][col];
                    int cb = input_buf[1][input_row + component1RowOffset][col];
                    int cr = input_buf[2][input_row + component2RowOffset][col];

                    /* Range-limiting is essential due to noise introduced by DCT losses.
                     * for extended gamut (sYCC) and wide gamut (bg-sYCC) encodings.
                     */
                    output_buf[output_row + row][columnOffset + JpegConstants.RGB_RED]   = limit[limitOffset + y + m_Cr_r_tab[cr]];
                    output_buf[output_row + row][columnOffset + JpegConstants.RGB_GREEN] = limit[limitOffset + y + JpegUtils.RIGHT_SHIFT(m_Cb_g_tab[cb] + m_Cr_g_tab[cr], SCALEBITS)];
                    output_buf[output_row + row][columnOffset + JpegConstants.RGB_BLUE]  = limit[limitOffset + y + m_Cb_b_tab[cb]];
                    columnOffset += JpegConstants.RGB_PIXELSIZE;
                }

                input_row++;
            }
        }
예제 #4
0
        /// <summary>
        /// Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical.
        /// </summary>
        private void H2V2MergedUpSample(ComponentBuffer[] input_buf, int in_row_group_ctr, byte[][] output_buf)
        {
            var inputRow00   = in_row_group_ctr * 2;
            var inputIndex00 = 0;

            var inputRow01   = (in_row_group_ctr * 2) + 1;
            var inputIndex01 = 0;

            var inputIndex1 = 0;
            var inputIndex2 = 0;

            var outIndex0 = 0;
            var outIndex1 = 0;

            var limit       = m_cinfo.m_sample_range_limit;
            var limitOffset = m_cinfo.m_sampleRangeLimitOffset;

            /* Loop for each group of output pixels */
            for (var col = m_cinfo.outputWidth >> 1; col > 0; col--)
            {
                /* Do the chroma part of the calculation */
                int cb = input_buf[1][in_row_group_ctr][inputIndex1];
                inputIndex1++;

                int cr = input_buf[2][in_row_group_ctr][inputIndex2];
                inputIndex2++;

                var cred   = m_Cr_r_tab[cr];
                var cgreen = JpegUtils.RIGHT_SHIFT(m_Cb_g_tab[cb] + m_Cr_g_tab[cr], SCALEBITS);
                var cblue  = m_Cb_b_tab[cb];

                /* Fetch 4 Y values and emit 4 pixels */
                int y = input_buf[0][inputRow00][inputIndex00];
                inputIndex00++;

                output_buf[0][outIndex0 + JpegConstants.RGB_RED]   = limit[limitOffset + y + cred];
                output_buf[0][outIndex0 + JpegConstants.RGB_GREEN] = limit[limitOffset + y + cgreen];
                output_buf[0][outIndex0 + JpegConstants.RGB_BLUE]  = limit[limitOffset + y + cblue];
                outIndex0 += JpegConstants.RGB_PIXELSIZE;

                y = input_buf[0][inputRow00][inputIndex00];
                inputIndex00++;

                output_buf[0][outIndex0 + JpegConstants.RGB_RED]   = limit[limitOffset + y + cred];
                output_buf[0][outIndex0 + JpegConstants.RGB_GREEN] = limit[limitOffset + y + cgreen];
                output_buf[0][outIndex0 + JpegConstants.RGB_BLUE]  = limit[limitOffset + y + cblue];
                outIndex0 += JpegConstants.RGB_PIXELSIZE;

                y = input_buf[0][inputRow01][inputIndex01];
                inputIndex01++;

                output_buf[1][outIndex1 + JpegConstants.RGB_RED]   = limit[limitOffset + y + cred];
                output_buf[1][outIndex1 + JpegConstants.RGB_GREEN] = limit[limitOffset + y + cgreen];
                output_buf[1][outIndex1 + JpegConstants.RGB_BLUE]  = limit[limitOffset + y + cblue];
                outIndex1 += JpegConstants.RGB_PIXELSIZE;

                y = input_buf[0][inputRow01][inputIndex01];
                inputIndex01++;

                output_buf[1][outIndex1 + JpegConstants.RGB_RED]   = limit[limitOffset + y + cred];
                output_buf[1][outIndex1 + JpegConstants.RGB_GREEN] = limit[limitOffset + y + cgreen];
                output_buf[1][outIndex1 + JpegConstants.RGB_BLUE]  = limit[limitOffset + y + cblue];
                outIndex1 += JpegConstants.RGB_PIXELSIZE;
            }

            /* If image width is odd, do the last output column separately */
            if ((m_cinfo.outputWidth & 1) != 0)
            {
                int cb     = input_buf[1][in_row_group_ctr][inputIndex1];
                int cr     = input_buf[2][in_row_group_ctr][inputIndex2];
                var cred   = m_Cr_r_tab[cr];
                var cgreen = JpegUtils.RIGHT_SHIFT(m_Cb_g_tab[cb] + m_Cr_g_tab[cr], SCALEBITS);
                var cblue  = m_Cb_b_tab[cb];

                int y = input_buf[0][inputRow00][inputIndex00];
                output_buf[0][outIndex0 + JpegConstants.RGB_RED]   = limit[limitOffset + y + cred];
                output_buf[0][outIndex0 + JpegConstants.RGB_GREEN] = limit[limitOffset + y + cgreen];
                output_buf[0][outIndex0 + JpegConstants.RGB_BLUE]  = limit[limitOffset + y + cblue];

                y = input_buf[0][inputRow01][inputIndex01];
                output_buf[1][outIndex1 + JpegConstants.RGB_RED]   = limit[limitOffset + y + cred];
                output_buf[1][outIndex1 + JpegConstants.RGB_GREEN] = limit[limitOffset + y + cgreen];
                output_buf[1][outIndex1 + JpegConstants.RGB_BLUE]  = limit[limitOffset + y + cblue];
            }
        }