private bool compressFirstPass(byte[][][] input_buf)
{
int last_iMCU_row = m_cinfo.m_total_iMCU_rows - 1;
for (int ci = 0; ci < m_cinfo.m_num_components; ci++)
{
jpeg_component_info componentInfo = m_cinfo.Component_info[ci];
/* Align the virtual buffer for this component. */
JBLOCK[][] buffer = m_whole_image[ci].Access(m_iMCU_row_num * componentInfo.V_samp_factor,
componentInfo.V_samp_factor);
/* Count non-dummy DCT block rows in this iMCU row. */
int block_rows;
if (m_iMCU_row_num < last_iMCU_row)
{
block_rows = componentInfo.V_samp_factor;
}
else
{
/* NB: can't use last_row_height here, since may not be set! */
block_rows = componentInfo.height_in_blocks % componentInfo.V_samp_factor;
if (block_rows == 0)
block_rows = componentInfo.V_samp_factor;
}
int blocks_across = componentInfo.Width_in_blocks;
int h_samp_factor = componentInfo.H_samp_factor;
/* Count number of dummy blocks to be added at the right margin. */
int ndummy = blocks_across % h_samp_factor;
if (ndummy > 0)
ndummy = h_samp_factor - ndummy;
jpeg_forward_dct.forward_DCT_ptr forward_DCT = m_cinfo.m_fdct.forward_DCT[ci];
/* Perform DCT for all non-dummy blocks in this iMCU row. Each call
* on forward_DCT processes a complete horizontal row of DCT blocks.
*/
for (int block_row = 0; block_row < block_rows; block_row++)
{
forward_DCT(componentInfo, input_buf[ci],
buffer[block_row], block_row * componentInfo.DCT_v_scaled_size, 0, blocks_across);
if (ndummy > 0)
{
/* Create dummy blocks at the right edge of the image. */
Array.Clear(buffer[block_row][blocks_across].data, 0, buffer[block_row][blocks_across].data.Length);
short lastDC = buffer[block_row][blocks_across - 1][0];
for (int bi = 0; bi < ndummy; bi++)
buffer[block_row][blocks_across + bi][0] = lastDC;
}
}
/* If at end of image, create dummy block rows as needed.
* The tricky part here is that within each MCU, we want the DC values
* of the dummy blocks to match the last real block's DC value.
* This squeezes a few more bytes out of the resulting file...
*/
if (m_iMCU_row_num == last_iMCU_row)
{
blocks_across += ndummy; /* include lower right corner */
int MCUs_across = blocks_across / h_samp_factor;
for (int block_row = block_rows; block_row < componentInfo.V_samp_factor; block_row++)
{
for (int i = 0; i < blocks_across; i++)
Array.Clear(buffer[block_row][i].data, 0, buffer[block_row][i].data.Length);
int thisOffset = 0;
int lastOffset = 0;
for (int MCUindex = 0; MCUindex < MCUs_across; MCUindex++)
{
short lastDC = buffer[block_row - 1][lastOffset + h_samp_factor - 1][0];
for (int bi = 0; bi < h_samp_factor; bi++)
buffer[block_row][thisOffset + bi][0] = lastDC;
thisOffset += h_samp_factor; /* advance to next MCU in row */
lastOffset += h_samp_factor;
}
}
}
}
/* NB: compress_output will increment iMCU_row_num if successful.
* A suspension return will result in redoing all the work above next time.
*/
/* Emit data to the entropy encoder, sharing code with subsequent passes */
return compressOutput();
}