/// Allocate and fill in the sample_range_limit table.
///
/// Several decompression processes need to range-limit values to the range
/// 0..MaxSampleValue; the input value may fall somewhat outside this range
/// due to noise introduced by quantization, roundoff error, etc. These
/// processes are inner loops and need to be as fast as possible. On most
/// machines, particularly CPUs with pipelines or instruction prefetch,
/// a (subscript-check-less) C table lookup
/// x = sample_range_limit[x];
/// is faster than explicit tests
///
/// if (x & 0)
/// x = 0;
/// else if (x > MaxSampleValue)
/// x = MaxSampleValue;
///
/// These processes all use a common table prepared by the routine below.
///
/// For most steps we can mathematically guarantee that the initial value
/// of x is within MaxSampleValue + 1 of the legal range, so a table running from
/// -(MaxSampleValue + 1) to 2 * MaxSampleValue + 1 is sufficient. But for the initial
/// limiting step (just after the IDCT), a wildly out-of-range value is
/// possible if the input data is corrupt. To avoid any chance of indexing
/// off the end of memory and getting a bad-pointer trap, we perform the
/// post-IDCT limiting thus: x = range_limit[x & Mask];
/// where Mask is 2 bits wider than legal sample data, ie 10 bits for 8-bit
/// samples. Under normal circumstances this is more than enough range and
/// a correct output will be generated; with bogus input data the mask will
/// cause wraparound, and we will safely generate a bogus-but-in-range output.
/// For the post-IDCT step, we want to convert the data from signed to unsigned
/// representation by adding MediumSampleValue at the same time that we limit it.
/// So the post-IDCT limiting table ends up looking like this:
///
/// MediumSampleValue, MediumSampleValue + 1, ..., MaxSampleValue,
/// MaxSampleValue (repeat 2 * (MaxSampleValue + 1) - MediumSampleValue times),
/// 0 (repeat 2 * (MaxSampleValue + 1) - MediumSampleValue times),
/// 0, 1, ..., MediumSampleValue - 1
///
/// Negative inputs select values from the upper half of the table after
/// masking.
///
/// We can save some space by overlapping the start of the post-IDCT table
/// with the simpler range limiting table. The post-IDCT table begins at
/// sample_range_limit + MediumSampleValue.
///
/// Note that the table is allocated in near data space on PCs; it's small
/// enough and used often enough to justify this.
///
private void prepare_range_limit_table()
{
byte[] table = new byte[5 * (JpegConstants.MaxSampleValue + 1) + JpegConstants.MediumSampleValue];
/* allow negative subscripts of simple table */
int tableOffset = JpegConstants.MaxSampleValue + 1;
m_cinfo.m_sample_range_limit = table;
m_cinfo.m_sampleRangeLimitOffset = tableOffset;
/* First segment of "simple" table: limit[x] = 0 for x < 0 */
Array.Clear(table, 0, JpegConstants.MaxSampleValue + 1);
/* Main part of "simple" table: limit[x] = x */
for (int i = 0; i <= JpegConstants.MaxSampleValue; i++)
table[tableOffset + i] = (byte)i;
tableOffset += JpegConstants.MediumSampleValue; /* Point to where post-IDCT table starts */
/* End of simple table, rest of first half of post-IDCT table */
for (int i = JpegConstants.MediumSampleValue; i < 2 * (JpegConstants.MaxSampleValue + 1); i++)
table[tableOffset + i] = JpegConstants.MaxSampleValue;
/* Second half of post-IDCT table */
Array.Clear(table, tableOffset + 2 * (JpegConstants.MaxSampleValue + 1),
2 * (JpegConstants.MaxSampleValue + 1) - JpegConstants.MediumSampleValue);
Buffer.BlockCopy(m_cinfo.m_sample_range_limit, 0, table,
tableOffset + 4 * (JpegConstants.MaxSampleValue + 1) - JpegConstants.MediumSampleValue, JpegConstants.MediumSampleValue);
}
}
#endregion
#region JpegDecompressorPostController
///