private void DecodeScan(byte numberOfComponents, byte[] componentSelector, int resetInterval, JPEGBinaryReader jpegReader, ref byte marker)
{
//TODO: not necessary
jpegReader.eob_run = 0;
int mcuIndex = 0;
int mcuTotalIndex = 0;
// This loops through until a MarkerTagFound exception is
// found, if the marker tag is a RST (Restart Marker) it
// simply skips it and moves on this system does not handle
// corrupt data streams very well, it could be improved by
// handling misplaced restart markers.
int h = 0, v = 0;
int x = 0;
long lastPosition = jpegReader.BaseStream.Position;
//TODO: replace this with a loop which knows how much data to expect
while (true)
{
#region Inform caller of decode progress
if (ProgressUpdateMethod != null)
{
if (jpegReader.BaseStream.Position >= lastPosition + JpegDecoder.ProgressUpdateByteInterval)
{
lastPosition = jpegReader.BaseStream.Position;
ProgressUpdateMethod(lastPosition);
}
}
#endregion
try
{
// Loop though capturing MCU, instruct each
// component to read in its necessary count, for
// scaling factors the components automatically
// read in how much they need
// Sec A.2.2 from CCITT Rec. T.81 (1992 E)
bool interleaved = !(numberOfComponents == 1);
if (!interleaved)
{
JpegComponent comp = Scan.GetComponentById(componentSelector[0]);
comp.SetBlock(mcuIndex);
comp.DecodeMCU(jpegReader, h, v);
int mcus_per_line = mcus_per_row(comp);
int blocks_per_line = (int)Math.Ceiling((double)this.Width / (8 * comp.factorH));
// TODO: Explain the non-interleaved scan ------
h++; x++;
if (h == comp.factorH)
{
h = 0; mcuIndex++;
}
if ((x % mcus_per_line) == 0)
{
x = 0;
v++;
if (v == comp.factorV)
{
if (h != 0)
{
mcuIndex++; h = 0;
}
v = 0;
}
else
{
mcuIndex -= blocks_per_line;
// we were mid-block
if (h != 0)
{
mcuIndex++; h = 0;
}
}
}
// -----------------------------------------------
}
else // Components are interleaved
{
for (int compIndex = 0; compIndex < numberOfComponents; compIndex++)
{
JpegComponent comp = Scan.GetComponentById(componentSelector[compIndex]);
comp.SetBlock(mcuTotalIndex);
for (int j = 0; j < comp.factorV; j++)
{
for (int i = 0; i < comp.factorH; i++)
{
comp.DecodeMCU(jpegReader, i, j);
}
}
}
mcuIndex++;
mcuTotalIndex++;
}
}
// We've found a marker, see if the marker is a restart
// marker or just the next marker in the stream. If
// it's the next marker in the stream break out of the
// while loop, if it's just a restart marker skip it
catch (JPEGMarkerFoundException ex)
{
marker = ex.Marker;
// Handle JPEG Restart Markers, this is where the
// count of MCU's per interval is compared with
// the count actually obtained, if it's short then
// pad on some MCU's ONLY for components that are
// greater than one. Also restart the DC prediction
// to zero.
if (marker == JPEGMarker.RST0 ||
marker == JPEGMarker.RST1 ||
marker == JPEGMarker.RST2 ||
marker == JPEGMarker.RST3 ||
marker == JPEGMarker.RST4 ||
marker == JPEGMarker.RST5 ||
marker == JPEGMarker.RST6 ||
marker == JPEGMarker.RST7)
{
for (int compIndex = 0; compIndex < numberOfComponents; compIndex++)
{
JpegComponent comp = Scan.GetComponentById(componentSelector[compIndex]);
if (compIndex > 1)
{
comp.padMCU(mcuTotalIndex, resetInterval - mcuIndex);
}
comp.resetInterval();
}
mcuTotalIndex += (resetInterval - mcuIndex);
mcuIndex = 0;
}
else
{
break; // We're at the end of our scan, exit out.
}
}
}
}