private ReadResult decompress_onepass(ComponentBuffer[] output_buf)
{
int last_MCU_col = m_cinfo.m_MCUs_per_row - 1;
int last_iMCU_row = m_cinfo.m_total_iMCU_rows - 1;
/* Loop to process as much as one whole iMCU row */
for (int yoffset = m_MCU_vert_offset; yoffset < m_MCU_rows_per_iMCU_row; yoffset++)
{
for (int MCU_col_num = m_MCU_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++)
{
/* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */
if (m_cinfo.lim_Se != 0)
{
/* can bypass in DC only case */
for (int i = 0; i < m_cinfo.m_blocks_in_MCU; i++)
Array.Clear(m_MCU_buffer[i].data, 0, m_MCU_buffer[i].data.Length);
}
if (!m_cinfo.m_entropy.decode_mcu(m_MCU_buffer))
{
/* Suspension forced; update state counters and exit */
m_MCU_vert_offset = yoffset;
m_MCU_ctr = MCU_col_num;
return ReadResult.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 < m_cinfo.m_comps_in_scan; ci++)
{
jpeg_component_info componentInfo = m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[ci]];
/* Don't bother to IDCT an uninteresting component. */
if (!componentInfo.component_needed)
{
blkn += componentInfo.MCU_blocks;
continue;
}
int useful_width = (MCU_col_num < last_MCU_col) ? componentInfo.MCU_width : componentInfo.last_col_width;
int outputIndex = yoffset * componentInfo.DCT_v_scaled_size;
int start_col = MCU_col_num * componentInfo.MCU_sample_width;
for (int yindex = 0; yindex < componentInfo.MCU_height; yindex++)
{
if (m_cinfo.m_input_iMCU_row < last_iMCU_row || yoffset + yindex < componentInfo.last_row_height)
{
int output_col = start_col;
for (int xindex = 0; xindex < useful_width; xindex++)
{
m_cinfo.m_idct.inverse(componentInfo.Component_index,
m_MCU_buffer[blkn + xindex].data, output_buf[componentInfo.Component_index],
outputIndex, output_col);
output_col += componentInfo.DCT_h_scaled_size;
}
}
blkn += componentInfo.MCU_width;
outputIndex += componentInfo.DCT_v_scaled_size;
}
}
}
/* Completed an MCU row, but perhaps not an iMCU row */
m_MCU_ctr = 0;
}
/* Completed the iMCU row, advance counters for next one */
m_cinfo.m_output_iMCU_row++;
m_cinfo.m_input_iMCU_row++;
if (m_cinfo.m_input_iMCU_row < m_cinfo.m_total_iMCU_rows)
{
start_iMCU_row();
return ReadResult.JPEG_ROW_COMPLETED;
}
/* Completed the scan */
m_cinfo.m_inputctl.finish_input_pass();
return ReadResult.JPEG_SCAN_COMPLETED;
}