private bool JPEGDecodeRaw(byte[] buffer, int offset, int count, short plane)
{
// data is expected to be read in multiples of a scanline
int nrows = m_decompression.Image_height;
if (nrows != 0)
{
// Cb,Cr both have sampling factors 1, so this is correct
int clumps_per_line = m_decompression.Comp_info[1].Downsampled_width;
do
{
// Reload downsampled-data buffer if needed
if (m_scancount >= JpegConstants.DCTSIZE)
{
int n = m_decompression.Max_v_samp_factor * JpegConstants.DCTSIZE;
if (TIFFjpeg_read_raw_data(m_ds_buffer, n) != n)
return false;
m_scancount = 0;
}
// Fastest way to unseparate data is to make one pass over the scanline for
// each row of each component.
int clumpoffset = 0; // first sample in clump
for (int ci = 0; ci < m_decompression.Num_components; ci++)
{
int hsamp = m_decompression.Comp_info[ci].H_samp_factor;
int vsamp = m_decompression.Comp_info[ci].V_samp_factor;
for (int ypos = 0; ypos < vsamp; ypos++)
{
byte[] inBuf = m_ds_buffer[ci][m_scancount * vsamp + ypos];
int inptr = 0;
int outptr = offset + clumpoffset;
if (outptr >= buffer.Length)
break;
if (hsamp == 1)
{
// fast path for at least Cb and Cr
for (int nclump = clumps_per_line; nclump-- > 0; )
{
buffer[outptr] = inBuf[inptr];
inptr++;
outptr += m_samplesperclump;
}
}
else
{
// general case
for (int nclump = clumps_per_line; nclump-- > 0; )
{
for (int xpos = 0; xpos < hsamp; xpos++)
{
buffer[outptr + xpos] = inBuf[inptr];
inptr++;
}
outptr += m_samplesperclump;
}
}
clumpoffset += hsamp;
}
}
++m_scancount;
m_tif.m_row += m_v_sampling;
// increment/decrement of buffer and count is still incorrect, but should not matter
// TODO: resolve this
offset += m_bytesperline;
count -= m_bytesperline;
nrows -= m_v_sampling;
}
while (nrows > 0);
}
// Close down the decompressor if done.
return m_decompression.Output_scanline < m_decompression.Output_height || TIFFjpeg_finish_decompress();
}