Exemplo n.º 1
0
        // Consume input data and store it in the full-image coefficient buffer.
        // We read as much as one fully interleaved MCU row ("iMCU" row) per call,
        // ie, v_samp_factor block rows for each component in the scan.
        // Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
        static CONSUME_INPUT consume_data(jpeg_decompress cinfo)
        {
            jpeg_lossy_d_codec lossyd = (jpeg_lossy_d_codec)cinfo.coef;
            d_coef_controller  coef   = (d_coef_controller)lossyd.coef_private;

            short[][][][] buffer     = new short[MAX_COMPS_IN_SCAN][][][];
            int[]         buffer_ind = new int[MAX_COMPS_IN_SCAN];

            // Align the buffers for the components used in this scan.
            for (int ci = 0; ci < cinfo.comps_in_scan; ci++)
            {
                jpeg_component_info compptr = cinfo.cur_comp_info[ci];
                buffer[ci]     = coef.whole_image[compptr.component_index];
                buffer_ind[ci] = (int)cinfo.input_iMCU_row * compptr.v_samp_factor;
                // Note: entropy decoder expects buffer to be zeroed,
                // but this is handled automatically by the memory manager
                // because we requested a pre-zeroed array.
            }

            // Loop to process 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 < cinfo.MCUs_per_row; MCU_col_num++)            // index of current MCU within row
                {
                    // Construct list of pointers to DCT blocks belonging to this MCU
                    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];
                        uint start_col = MCU_col_num * (uint)compptr.MCU_width;
                        for (int yindex = 0; yindex < compptr.MCU_height; yindex++)
                        {
                            short[][] buffer_ptr     = buffer[ci][buffer_ind[ci] + yindex + yoffset];
                            uint      buffer_ptr_ind = start_col;
                            for (int xindex = 0; xindex < compptr.MCU_width; xindex++)
                            {
                                coef.MCU_buffer[blkn++] = buffer_ptr[buffer_ptr_ind++];
                            }
                        }
                    }

                    // Try to fetch the MCU.
                    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);
                    }
                }

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

            // Completed the iMCU row, advance counters for next one
            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);
        }
Exemplo n.º 2
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);
        }