private bool get_sos()
{
if (!m_cinfo.m_marker.m_saw_SOF)
m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_SOF_BEFORE, "SOS");
int length;
if (!m_cinfo.m_src.GetTwoBytes(out length))
return false;
/* Number of components */
int n;
if (!m_cinfo.m_src.GetByte(out n))
return false;
m_cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_SOS, n);
if (length != (n * 2 + 6) || n > JpegConstants.MAX_COMPS_IN_SCAN ||
(n == 0 && m_cinfo.m_progressive_mode))
{
/* pseudo SOS marker only allowed in progressive mode */
m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_LENGTH);
}
m_cinfo.m_comps_in_scan = n;
/* Collect the component-spec parameters */
for (int i = 0; i < n; i++)
{
int c;
if (!m_cinfo.m_src.GetByte(out c))
return false;
/* Detect the case where component id's are not unique, and, if so, */
/* create a fake component id using the same logic as in get_sof. */
/* Note: This also ensures that all of the SOF components are */
/* referenced in the single scan case, which prevents access to */
/* uninitialized memory in later decoding stages. */
for (int ci = 0; ci < i; ci++)
{
jpeg_component_info componentInfo = m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[ci]];
if (c == componentInfo.Component_id)
{
componentInfo = m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[0]];
c = componentInfo.Component_id;
for (ci = 1; ci < i; ci++)
{
componentInfo = m_cinfo.Comp_info[m_cinfo.m_cur_comp_info[ci]];
if (componentInfo.Component_id > c)
c = componentInfo.Component_id;
}
c++;
break;
}
}
bool idFound = false;
int foundIndex = -1;
for (int ci = 0; ci < m_cinfo.m_num_components; ci++)
{
if (c == m_cinfo.Comp_info[ci].Component_id)
{
foundIndex = ci;
idFound = true;
break;
}
}
if (!idFound)
m_cinfo.ERREXIT(J_MESSAGE_CODE.JERR_BAD_COMPONENT_ID, c);
m_cinfo.m_cur_comp_info[i] = foundIndex;
if (!m_cinfo.m_src.GetByte(out c))
return false;
m_cinfo.Comp_info[foundIndex].Dc_tbl_no = (c >> 4) & 15;
m_cinfo.Comp_info[foundIndex].Ac_tbl_no = (c) & 15;
m_cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_SOS_COMPONENT,
m_cinfo.Comp_info[foundIndex].Component_id,
m_cinfo.Comp_info[foundIndex].Dc_tbl_no,
m_cinfo.Comp_info[foundIndex].Ac_tbl_no);
}
/* Collect the additional scan parameters Ss, Se, Ah/Al. */
int temp;
if (!m_cinfo.m_src.GetByte(out temp))
return false;
m_cinfo.m_Ss = temp;
if (!m_cinfo.m_src.GetByte(out temp))
return false;
m_cinfo.m_Se = temp;
if (!m_cinfo.m_src.GetByte(out temp))
return false;
m_cinfo.m_Ah = (temp >> 4) & 15;
m_cinfo.m_Al = (temp) & 15;
m_cinfo.TRACEMS(1, J_MESSAGE_CODE.JTRC_SOS_PARAMS, m_cinfo.m_Ss, m_cinfo.m_Se, m_cinfo.m_Ah, m_cinfo.m_Al);
/* Prepare to scan data & restart markers */
m_cinfo.m_marker.m_next_restart_num = 0;
/* Count another (non-pseudo) SOS marker */
if (n != 0)
m_cinfo.m_input_scan_number++;
return true;
}