void Scan::ParseMarker(class ByteStream *io,ScanType type)
{
  LONG len = io->GetWord();
  LONG data;
  int i,j;

  if (len < 8)
    JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","marker length of the SOS marker invalid, must be at least 8 bytes long");

  data = io->Get();
  if (data < 1 || data > 4)
    JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","number of components in scan is invalid, must be between 1 and 4");

  m_ucCount = data;

  if (len != m_ucCount * 2 + 6)
    JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","length of the SOS marker is invalid");

  for(i = 0;i < m_ucCount;i++) {
    data = io->Get(); // component identifier.
    if (data == ByteStream::EOF)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","SOS marker run out of data");

    m_ucComponent[i] = data;
    for(j = 0;j < i;j++) {
      if (m_ucComponent[j] == data)
        JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","SOS includes the same component twice");
    }
    
    data = io->Get(); // table selectors.
    if (data == ByteStream::EOF)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","SOS marker run out of data");

    if (m_pFrame->ScanTypeOf() != JPEG_LS) {
      m_ucDCTable[i] = data >> 4;
      m_ucACTable[i] = data & 0x0f;
      
      if (m_ucDCTable[i] > 3)
        JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","DC table index in SOS marker is out of range, must be at most 4");
      
      if (m_ucACTable[i] > 3)
        JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","AC table index in SOS marker is out of range, must be at most 4");
    } else {
      m_ucMappingTable[i] = data; // JPEG_LS uses this for the mapping table selector.
      // The VESA scan types may use this, but the tables are hardwired.
      m_ucDCTable[i]      = (i == 0)?(0):(1);
      m_ucACTable[i]      = (i == 0)?(0):(1);
    }
  }

  // Start of spectral selection or NEAR value.
  data = io->Get();
  if (data == ByteStream::EOF)
    JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","SOS marker run out of data");
  if (data > 63 && m_pFrame->ScanTypeOf() != JPEG_LS)
    JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","start of scan index is out of range, must be between 0 and 63");
  m_ucScanStart = data;
  
  //
  // End of spectral selection or interleave specifier.
  data = io->Get();
  if (data == ByteStream::EOF)
    JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","SOS marker run out of data");
  if (m_pFrame->ScanTypeOf() != JPEG_LS) {
    if (data > 63)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","end of scan index is out of range, must be between 0 and 63");
  } else {
    if (data > 2)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","interleave specification is out of range, must be between 0 and 2"); 
  }
  m_ucScanStop = data;
  
  data = io->Get();
  if (data == ByteStream::EOF)
    JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","SOS marker run out of data");

  m_ucHighBit    = data >> 4;
  m_ucLowBit     = data & 0x0f;
  m_ucHiddenBits = m_pFrame->TablesOf()->HiddenDCTBitsOf();

  if (m_ucHighBit > 13)
    JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","SOS high bit approximation is out of range, must be < 13");

  switch(type) {
  case Progressive:
  case ACProgressive:
  case DifferentialProgressive:
  case ACDifferentialProgressive:
    if (m_ucHighBit && m_ucHighBit != m_ucLowBit + 1)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "SOS high bit is invalid, successive approximation must refine by one bit per scan");
    if (m_ucScanStop < m_ucScanStart)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","end of scan is lower than start of scan");
    if (m_ucScanStart == 0 && m_ucScanStop != 0)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","DC component must be in a separate scan in the progressive mode");
    if (m_ucScanStart && m_ucCount != 1)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","AC scans in progressive mode must only contain a single component");
    break;
  case Residual:
  case ACResidual:
  case ResidualProgressive:
  case ACResidualProgressive:
  case ResidualDCT:
  case ACResidualDCT:
    if (m_ucHighBit && m_ucHighBit != m_ucLowBit + 1)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "SOS high bit is invalid, successive approximation must refine by one bit per scan");
    if (m_ucScanStop < m_ucScanStart)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","end of scan is lower than start of scan");
    break;
  case Baseline:
  case Sequential:
  case ACSequential:
  case DifferentialSequential:
  case ACDifferentialSequential:
    if (m_ucScanStop != 63 || m_ucScanStart != 0)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "scan start must be zero and scan stop must be 63 for the sequential operating modes");
    // fall through
  case JPEG_LS: 
    // Specs don't say anything what to do about them. Just assume they must be zero.
    if (m_ucHighBit != 0) // Low bit is the point transformation
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "successive approximation parameters must be zero for the sequential operating modes");
    break;
  case Lossless:
  case ACLossless:
    if (m_ucScanStart == 0 || m_ucScanStop > 7) // actually the predictor.
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "predictor for the lossless mode must be between 1 and 7");
    if (m_ucScanStop != 0)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "scan stop parameter must be zero in the lossless mode");
    if (m_ucHighBit != 0)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "successive approximation high bit parameter must be zero for the lossless mode");
    break;
  case DifferentialLossless:
  case ACDifferentialLossless:
    if (m_ucScanStart != 0) // actually the predictor.
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "predictor for the differential lossless mode must be zero");
    if (m_ucScanStop != 0)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "scan stop parameter must be zero in the lossless mode");
    if (m_ucHighBit != 0)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "successive approximation high bit parameter must be zero for the lossless mode");
    break;
  default:
    break;
  }
}
void Scan::ParseMarker(class ByteStream *io,ScanType type)
{
  LONG len = io->GetWord();
  LONG data;
  int i,j;

  if (len < 8)
    JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","marker length of the SOS marker invalid, must be at least 8 bytes long");

  data = io->Get();
  if (data < 1 || data > 4)
    JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","number of components in scan is invalid, must be between 1 and 4");

  m_ucCount = data;

  if (len != m_ucCount * 2 + 6)
    JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","length of the SOS marker is invalid");

  for(i = 0;i < m_ucCount;i++) {
    data = io->Get();  
    if (data == ByteStream::EOF)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","SOS marker run out of data");

    m_ucComponent[i] = data;
    for(j = 0;j < i;j++) {
      if (m_ucComponent[j] == data)
        JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","SOS includes the same component twice");
    }
    
    data = io->Get();  
    if (data == ByteStream::EOF)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","SOS marker run out of data");

    if (m_pFrame->ScanTypeOf() != JPEG_LS) {
      m_ucDCTable[i] = data >> 4;
      m_ucACTable[i] = data & 0x0f;
      
      if (m_ucDCTable[i] > 3)
        JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","DC table index in SOS marker is out of range, must be at most 4");
      
      if (m_ucACTable[i] > 3)
        JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","AC table index in SOS marker is out of range, must be at most 4");
    } else {
      m_ucMappingTable[i] = data;  
       
      m_ucDCTable[i]      = (i == 0)?(0):(1);
      m_ucACTable[i]      = (i == 0)?(0):(1);
    }
  }

   
  data = io->Get();
  if (data == ByteStream::EOF)
    JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","SOS marker run out of data");
  if (data > 63 && m_pFrame->ScanTypeOf() != JPEG_LS)
    JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","start of scan index is out of range, must be between 0 and 63");
  m_ucScanStart = data;
  
   
   
  data = io->Get();
  if (data == ByteStream::EOF)
    JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","SOS marker run out of data");
  if (m_pFrame->ScanTypeOf() != JPEG_LS) {
    if (data > 63)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","end of scan index is out of range, must be between 0 and 63");
  } else {
    if (data > 2)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","interleave specification is out of range, must be between 0 and 2"); 
  }
  m_ucScanStop = data;
  
  data = io->Get();
  if (data == ByteStream::EOF)
    JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","SOS marker run out of data");

  m_ucHighBit    = data >> 4;
  m_ucLowBit     = data & 0x0f;
  m_ucHiddenBits = m_pFrame->TablesOf()->HiddenDCTBitsOf();

  if (m_ucHighBit > 13)
    JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","SOS high bit approximation is out of range, must be < 13");

  switch(type) {
  case Progressive:
  case ACProgressive:
  case DifferentialProgressive:
  case ACDifferentialProgressive:
    if (m_ucHighBit && m_ucHighBit != m_ucLowBit + 1)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "SOS high bit is invalid, successive approximation must refine by one bit per scan");
    if (m_ucScanStop < m_ucScanStart)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","end of scan is lower than start of scan");
    if (m_ucScanStart == 0 && m_ucScanStop != 0)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","DC component must be in a separate scan in the progressive mode");
    if (m_ucScanStart && m_ucCount != 1)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","AC scans in progressive mode must only contain a single component");
    break;
  case Residual:
  case ACResidual:
  case ResidualProgressive:
  case ACResidualProgressive:
  case ResidualDCT:
  case ACResidualDCT:
    if (m_ucHighBit && m_ucHighBit != m_ucLowBit + 1)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "SOS high bit is invalid, successive approximation must refine by one bit per scan");
    if (m_ucScanStop < m_ucScanStart)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker","end of scan is lower than start of scan");
    break;
  case Baseline:
  case Sequential:
  case ACSequential:
  case DifferentialSequential:
  case ACDifferentialSequential:
    if (m_ucScanStop != 63 || m_ucScanStart != 0)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "scan start must be zero and scan stop must be 63 for the sequential operating modes");
     
  case JPEG_LS: 
     
    if (m_ucHighBit != 0)  
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "successive approximation parameters must be zero for the sequential operating modes");
    break;
  case Lossless:
  case ACLossless:
    if (m_ucScanStart == 0 || m_ucScanStop > 7)  
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "predictor for the lossless mode must be between 1 and 7");
    if (m_ucScanStop != 0)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "scan stop parameter must be zero in the lossless mode");
    if (m_ucHighBit != 0)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "successive approximation high bit parameter must be zero for the lossless mode");
    break;
  case DifferentialLossless:
  case ACDifferentialLossless:
    if (m_ucScanStart != 0)  
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "predictor for the differential lossless mode must be zero");
    if (m_ucScanStop != 0)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "scan stop parameter must be zero in the lossless mode");
    if (m_ucHighBit != 0)
      JPG_THROW(MALFORMED_STREAM,"Scan::ParseMarker",
                "successive approximation high bit parameter must be zero for the lossless mode");
    break;
  default:
    break;
  }
}