Пример #1
0
        // Decompress and return some data in the multi-pass case.
        // Always attempts to emit one fully interleaved MCU row ("iMCU" row).
        // Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
        //
        // NB: output_buf contains a plane for each component in image.
        static CONSUME_INPUT decompress_data(jpeg_decompress cinfo, byte[][][] output_buf)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;
            d_coef_controller  coef   = (d_coef_controller)lossyd.coef_private;

            uint last_iMCU_row = cinfo.total_iMCU_rows - 1;

            // Force some input to be done if we are getting ahead of the input.
            while (cinfo.input_scan_number < cinfo.output_scan_number || (cinfo.input_scan_number == cinfo.output_scan_number && cinfo.input_iMCU_row <= cinfo.output_iMCU_row))
            {
                if (cinfo.inputctl.consume_input(cinfo) == CONSUME_INPUT.JPEG_SUSPENDED)
                {
                    return(CONSUME_INPUT.JPEG_SUSPENDED);
                }
            }

            // OK, output from the arrays.
            for (int ci = 0; ci < cinfo.num_components; ci++)
            {
                jpeg_component_info compptr = cinfo.comp_info[ci];

                // Don't bother to IDCT an uninteresting component.
                if (!compptr.component_needed)
                {
                    continue;
                }

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

                // Count non-dummy DCT block rows in this iMCU row.
                int block_rows;
                if (cinfo.output_iMCU_row < last_iMCU_row)
                {
                    block_rows = compptr.v_samp_factor;
                }
                else
                {
                    // NB: can't use last_row_height here; it is input-side-dependent!
                    block_rows = (int)(compptr.height_in_blocks % compptr.v_samp_factor);
                    if (block_rows == 0)
                    {
                        block_rows = compptr.v_samp_factor;
                    }
                }
                inverse_DCT_method_ptr inverse_DCT = lossyd.inverse_DCT[ci];
                byte[][] output_ptr     = output_buf[ci];
                uint     output_ptr_ind = 0;

                // Loop over all DCT blocks to be processed.
                for (int block_row = 0; block_row < block_rows; block_row++)
                {
                    short[][] buffer_ptr = buffer[buffer_ind + block_row];
                    uint      output_col = 0;
                    for (uint block_num = 0; block_num < compptr.width_in_blocks; block_num++)
                    {
                        inverse_DCT(cinfo, compptr, buffer_ptr[block_num], output_ptr, output_ptr_ind, output_col);
                        output_col += compptr.DCT_scaled_size;
                    }
                    output_ptr_ind += compptr.DCT_scaled_size;
                }
            }

            if (++(cinfo.output_iMCU_row) < cinfo.total_iMCU_rows)
            {
                return(CONSUME_INPUT.JPEG_ROW_COMPLETED);
            }
            return(CONSUME_INPUT.JPEG_SCAN_COMPLETED);
        }
Пример #2
0
        // Variant of decompress_data for use when doing block smoothing.
        static CONSUME_INPUT decompress_smooth_data(jpeg_decompress cinfo, byte[][][] output_buf)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;
            d_coef_controller  coef   = (d_coef_controller)lossyd.coef_private;

            // Force some input to be done if we are getting ahead of the input.
            while (cinfo.input_scan_number <= cinfo.output_scan_number && !cinfo.inputctl.eoi_reached)
            {
                if (cinfo.input_scan_number == cinfo.output_scan_number)
                {
                    // If input is working on current scan, we ordinarily want it to
                    // have completed the current row. But if input scan is DC,
                    // we want it to keep one row ahead so that next block row's DC
                    // values are up to date.
                    uint delta = (cinfo.Ss == 0)?1u:0u;
                    if (cinfo.input_iMCU_row > cinfo.output_iMCU_row + delta)
                    {
                        break;
                    }
                }
                if (cinfo.inputctl.consume_input(cinfo) == CONSUME_INPUT.JPEG_SUSPENDED)
                {
                    return(CONSUME_INPUT.JPEG_SUSPENDED);
                }
            }

            uint last_iMCU_row = cinfo.total_iMCU_rows - 1;

            short[] workspace = new short[DCTSIZE2];

            // OK, output from the arrays.
            for (int ci = 0; ci < cinfo.num_components; ci++)
            {
                jpeg_component_info compptr = cinfo.comp_info[ci];

                // Don't bother to IDCT an uninteresting component.
                if (!compptr.component_needed)
                {
                    continue;
                }

                // Count non-dummy DCT block rows in this iMCU row.
                int  block_rows, access_rows;
                bool last_row;
                if (cinfo.output_iMCU_row < last_iMCU_row)
                {
                    block_rows  = compptr.v_samp_factor;
                    access_rows = block_rows * 2;                 // this and next iMCU row
                    last_row    = false;
                }
                else
                {
                    // NB: can't use last_row_height here; it is input-side-dependent!
                    block_rows = (int)(compptr.height_in_blocks % compptr.v_samp_factor);
                    if (block_rows == 0)
                    {
                        block_rows = compptr.v_samp_factor;
                    }
                    access_rows = block_rows;                   // this iMCU row only
                    last_row    = true;
                }

                // Align the buffer for this component.
                bool        first_row;
                short[][][] buffer;
                int         buffer_ind;
                if (cinfo.output_iMCU_row > 0)
                {
                    access_rows += compptr.v_samp_factor;                              // prior iMCU row too
                    buffer       = coef.whole_image[ci];
                    buffer_ind   = (int)cinfo.output_iMCU_row * compptr.v_samp_factor; // point to current iMCU row
                    first_row    = false;
                }
                else
                {
                    buffer     = coef.whole_image[ci];
                    buffer_ind = 0;
                    first_row  = true;
                }

                // Fetch component-dependent info
                int[]                  coef_bits      = coef.coef_bits_latch[ci];
                JQUANT_TBL             quanttbl       = compptr.quant_table;
                int                    Q00            = quanttbl.quantval[0];
                int                    Q01            = quanttbl.quantval[Q01_POS];
                int                    Q10            = quanttbl.quantval[Q10_POS];
                int                    Q20            = quanttbl.quantval[Q20_POS];
                int                    Q11            = quanttbl.quantval[Q11_POS];
                int                    Q02            = quanttbl.quantval[Q02_POS];
                inverse_DCT_method_ptr inverse_DCT    = lossyd.inverse_DCT[ci];
                uint                   output_buf_ind = 0;

                // Loop over all DCT blocks to be processed.
                for (int block_row = 0; block_row < block_rows; block_row++)
                {
                    short[][] buffer_ptr = buffer[buffer_ind + block_row];
                    short[][] prev_block_row;
                    short[][] next_block_row;

                    if (first_row && block_row == 0)
                    {
                        prev_block_row = buffer_ptr;
                    }
                    else
                    {
                        prev_block_row = buffer[buffer_ind + block_row - 1];
                    }
                    if (last_row && block_row == block_rows - 1)
                    {
                        next_block_row = buffer_ptr;
                    }
                    else
                    {
                        next_block_row = buffer[buffer_ind + block_row + 1];
                    }

                    // We fetch the surrounding DC values using a sliding-register approach.
                    // Initialize all nine here so as to do the right thing on narrow pics.
                    int DC1, DC2, DC3, DC4, DC5, DC6, DC7, DC8, DC9;
                    DC1 = DC2 = DC3 = (int)prev_block_row[0][0];
                    DC4 = DC5 = DC6 = (int)buffer_ptr[0][0];
                    DC7 = DC8 = DC9 = (int)next_block_row[0][0];
                    int ind = 1;

                    uint output_col = 0;

                    uint last_block_column = compptr.width_in_blocks - 1;
                    for (uint block_num = 0; block_num <= last_block_column; block_num++)
                    {
                        // Fetch current DCT block into workspace so we can modify it.
                        buffer_ptr.CopyTo(workspace, 0);

                        // Update DC values
                        if (block_num < last_block_column)
                        {
                            DC3 = (int)prev_block_row[ind][0];
                            DC6 = (int)buffer_ptr[ind][0];
                            DC9 = (int)next_block_row[ind][0];
                        }
                        // Compute coefficient estimates per K.8.
                        // An estimate is applied only if coefficient is still zero,
                        // and is not known to be fully accurate.

                        // AC01
                        int Al = coef_bits[1];
                        if (Al != 0 && workspace[1] == 0)
                        {
                            int num = 36 * Q00 * (DC4 - DC6);
                            int pred;
                            if (num >= 0)
                            {
                                pred = (int)(((Q01 << 7) + num) / (Q01 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                            }
                            else
                            {
                                pred = (int)(((Q01 << 7) - num) / (Q01 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                                pred = -pred;
                            }
                            workspace[1] = (short)pred;
                        }

                        // AC10
                        Al = coef_bits[2];
                        if (Al != 0 && workspace[8] == 0)
                        {
                            int num = 36 * Q00 * (DC2 - DC8);
                            int pred;
                            if (num >= 0)
                            {
                                pred = (int)(((Q10 << 7) + num) / (Q10 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                            }
                            else
                            {
                                pred = (int)(((Q10 << 7) - num) / (Q10 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                                pred = -pred;
                            }
                            workspace[8] = (short)pred;
                        }

                        // AC20
                        Al = coef_bits[3];
                        if (Al != 0 && workspace[16] == 0)
                        {
                            int num = 9 * Q00 * (DC2 + DC8 - 2 * DC5);
                            int pred;
                            if (num >= 0)
                            {
                                pred = (int)(((Q20 << 7) + num) / (Q20 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                            }
                            else
                            {
                                pred = (int)(((Q20 << 7) - num) / (Q20 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                                pred = -pred;
                            }
                            workspace[16] = (short)pred;
                        }

                        // AC11
                        Al = coef_bits[4];
                        if (Al != 0 && workspace[9] == 0)
                        {
                            int num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
                            int pred;
                            if (num >= 0)
                            {
                                pred = (int)(((Q11 << 7) + num) / (Q11 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                            }
                            else
                            {
                                pred = (int)(((Q11 << 7) - num) / (Q11 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                                pred = -pred;
                            }
                            workspace[9] = (short)pred;
                        }

                        // AC02
                        Al = coef_bits[5];
                        if (Al != 0 && workspace[2] == 0)
                        {
                            int num = 9 * Q00 * (DC4 + DC6 - 2 * DC5);
                            int pred;
                            if (num >= 0)
                            {
                                pred = (int)(((Q02 << 7) + num) / (Q02 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                            }
                            else
                            {
                                pred = (int)(((Q02 << 7) - num) / (Q02 << 8));
                                if (Al > 0 && pred >= (1 << Al))
                                {
                                    pred = (1 << Al) - 1;
                                }
                                pred = -pred;
                            }
                            workspace[2] = (short)pred;
                        }

                        // OK, do the IDCT
                        inverse_DCT(cinfo, compptr, workspace, output_buf[ci], output_buf_ind, output_col);

                        // Advance for next column
                        DC1 = DC2; DC2 = DC3;
                        DC4 = DC5; DC5 = DC6;
                        DC7 = DC8; DC8 = DC9;
                        ind++;
                        output_col += compptr.DCT_scaled_size;
                    }
                    output_buf_ind += compptr.DCT_scaled_size;
                }
            }

            if (++(cinfo.output_iMCU_row) < cinfo.total_iMCU_rows)
            {
                return(CONSUME_INPUT.JPEG_ROW_COMPLETED);
            }
            return(CONSUME_INPUT.JPEG_SCAN_COMPLETED);
        }
Пример #3
0
        // Decompress and return some data in the single-pass case.
        // Always attempts to emit one fully interleaved MCU row ("iMCU" row).
        // Input and output must run in lockstep since we have only a one-MCU buffer.
        // Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
        //
        // NB: output_buf contains a plane for each component in image,
        // which we index according to the component's SOF position.
        static CONSUME_INPUT decompress_onepass(jpeg_decompress cinfo, byte[][][] output_buf)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;
            d_coef_controller  coef   = (d_coef_controller)lossyd.coef_private;

            uint last_MCU_col  = cinfo.MCUs_per_row - 1;
            uint last_iMCU_row = cinfo.total_iMCU_rows - 1;

            // Loop to process 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
                {
                    // Try to fetch an MCU. Entropy decoder expects buffer to be zeroed.
                    for (int i = 0; i < cinfo.blocks_in_MCU; i++)
                    {
                        for (int a = 0; a < DCTSIZE2; a++)
                        {
                            coef.MCU_buffer[i][a] = 0;
                        }
                    }

                    if (!lossyd.entropy_decode_mcu(cinfo, coef.MCU_buffer))
                    {
                        // Suspension forced; update state counters and exit
                        coef.MCU_vert_offset = yoffset;
                        coef.MCU_ctr         = MCU_col_num;
                        return(CONSUME_INPUT.JPEG_SUSPENDED);
                    }

                    // Determine where data should go in output_buf and do the IDCT thing.
                    // We skip dummy blocks at the right and bottom edges (but blkn gets
                    // incremented past them!). Note the inner loop relies on having
                    // allocated the MCU_buffer[] blocks sequentially.
                    int blkn = 0;                   // index of current DCT block within MCU
                    for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
                    {
                        jpeg_component_info compptr = cinfo.cur_comp_info[ci];

                        // Don't bother to IDCT an uninteresting component.
                        if (!compptr.component_needed)
                        {
                            blkn += (int)compptr.MCU_blocks;
                            continue;
                        }

                        inverse_DCT_method_ptr inverse_DCT = lossyd.inverse_DCT[compptr.component_index];

                        int useful_width = (MCU_col_num < last_MCU_col)?compptr.MCU_width:compptr.last_col_width;

                        byte[][] output_ptr     = output_buf[compptr.component_index];
                        uint     output_ptr_ind = (uint)yoffset * compptr.DCT_scaled_size;

                        uint start_col = MCU_col_num * (uint)compptr.MCU_sample_width;

                        for (int yindex = 0; yindex < compptr.MCU_height; yindex++)
                        {
                            if (cinfo.input_iMCU_row < last_iMCU_row || yoffset + yindex < compptr.last_row_height)
                            {
                                uint output_col = start_col;
                                for (int xindex = 0; xindex < useful_width; xindex++)
                                {
                                    inverse_DCT(cinfo, compptr, coef.MCU_buffer[blkn + xindex], output_ptr, output_ptr_ind, output_col);
                                    output_col += compptr.DCT_scaled_size;
                                }
                            }
                            blkn           += compptr.MCU_width;
                            output_ptr_ind += compptr.DCT_scaled_size;
                        }
                    }
                }

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

            // Completed the iMCU row, advance counters for next one
            cinfo.output_iMCU_row++;
            if (++(cinfo.input_iMCU_row) < cinfo.total_iMCU_rows)
            {
                start_iMCU_row_d_coef(cinfo);
                return(CONSUME_INPUT.JPEG_ROW_COMPLETED);
            }

            // Completed the scan
            cinfo.inputctl.finish_input_pass(cinfo);
            return(CONSUME_INPUT.JPEG_SCAN_COMPLETED);
        }