private void validate_script()
{
if (m_num_scans <= 0)
ERREXIT(J_MESSAGE_CODE.JERR_BAD_SCAN_SCRIPT, 0);
/* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1;
* for progressive JPEG, no scan can have this.
*/
int[][] last_bitpos = new int[JpegConstants.MAX_COMPONENTS][];
for (int i = 0; i < JpegConstants.MAX_COMPONENTS; i++)
last_bitpos[i] = new int[JpegConstants.DCTSIZE2];
bool[] component_sent = new bool[JpegConstants.MAX_COMPONENTS];
/* -1 until that coefficient has been seen; then last Al for it */
if (m_scan_info[0].Ss != 0 || m_scan_info[0].Se != JpegConstants.DCTSIZE2 - 1)
{
m_progressive_mode = true;
for (int ci = 0; ci < m_num_components; ci++)
{
for (int coefi = 0; coefi < JpegConstants.DCTSIZE2; coefi++)
last_bitpos[ci][coefi] = -1;
}
}
else
{
m_progressive_mode = false;
for (int ci = 0; ci < m_num_components; ci++)
component_sent[ci] = false;
}
for (int scanno = 1; scanno <= m_num_scans; scanno++)
{
jpeg_scan_info scanInfo = m_scan_info[scanno - 1];
/* Validate component indexes */
int ncomps = scanInfo.comps_in_scan;
if (ncomps <= 0 || ncomps > JpegConstants.MAX_COMPS_IN_SCAN)
ERREXIT(J_MESSAGE_CODE.JERR_COMPONENT_COUNT, ncomps, JpegConstants.MAX_COMPS_IN_SCAN);
for (int ci = 0; ci < ncomps; ci++)
{
int thisi = scanInfo.component_index[ci];
if (thisi < 0 || thisi >= m_num_components)
ERREXIT(J_MESSAGE_CODE.JERR_BAD_SCAN_SCRIPT, scanno);
/* Components must appear in SOF order within each scan */
if (ci > 0 && thisi <= scanInfo.component_index[ci - 1])
ERREXIT(J_MESSAGE_CODE.JERR_BAD_SCAN_SCRIPT, scanno);
}
/* Validate progression parameters */
int Ss = scanInfo.Ss;
int Se = scanInfo.Se;
int Ah = scanInfo.Ah;
int Al = scanInfo.Al;
if (m_progressive_mode)
{
/* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that
* seems wrong: the upper bound ought to depend on data precision.
* Perhaps they really meant 0..N+1 for N-bit precision.
* Here we allow 0..10 for 8-bit data; Al larger than 10 results in
* out-of-range reconstructed DC values during the first DC scan,
* which might cause problems for some decoders.
*/
const int MAX_AH_AL = 10;
if (Ss < 0 || Ss >= JpegConstants.DCTSIZE2 || Se < Ss || Se >= JpegConstants.DCTSIZE2 ||
Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL)
{
ERREXIT(J_MESSAGE_CODE.JERR_BAD_PROG_SCRIPT, scanno);
}
if (Ss == 0)
{
if (Se != 0) /* DC and AC together not OK */
ERREXIT(J_MESSAGE_CODE.JERR_BAD_PROG_SCRIPT, scanno);
}
else
{
if (ncomps != 1) /* AC scans must be for only one component */
ERREXIT(J_MESSAGE_CODE.JERR_BAD_PROG_SCRIPT, scanno);
}
for (int ci = 0; ci < ncomps; ci++)
{
int lastBitComponentIndex = scanInfo.component_index[ci];
if (Ss != 0 && last_bitpos[lastBitComponentIndex][0] < 0) /* AC without prior DC scan */
ERREXIT(J_MESSAGE_CODE.JERR_BAD_PROG_SCRIPT, scanno);
for (int coefi = Ss; coefi <= Se; coefi++)
{
if (last_bitpos[lastBitComponentIndex][coefi] < 0)
{
/* first scan of this coefficient */
if (Ah != 0)
ERREXIT(J_MESSAGE_CODE.JERR_BAD_PROG_SCRIPT, scanno);
}
else
{
/* not first scan */
if (Ah != last_bitpos[lastBitComponentIndex][coefi] || Al != Ah - 1)
ERREXIT(J_MESSAGE_CODE.JERR_BAD_PROG_SCRIPT, scanno);
}
last_bitpos[lastBitComponentIndex][coefi] = Al;
}
}
}
else
{
/* For sequential JPEG, all progression parameters must be these: */
if (Ss != 0 || Se != JpegConstants.DCTSIZE2 - 1 || Ah != 0 || Al != 0)
ERREXIT(J_MESSAGE_CODE.JERR_BAD_PROG_SCRIPT, scanno);
/* Make sure components are not sent twice */
for (int ci = 0; ci < ncomps; ci++)
{
int thisi = scanInfo.component_index[ci];
if (component_sent[thisi])
ERREXIT(J_MESSAGE_CODE.JERR_BAD_SCAN_SCRIPT, scanno);
component_sent[thisi] = true;
}
}
}
/* Now verify that everything got sent. */
if (m_progressive_mode)
{
/* For progressive mode, we only check that at least some DC data
* got sent for each component; the spec does not require that all bits
* of all coefficients be transmitted. Would it be wiser to enforce
* transmission of all coefficient bits??
*/
for (int ci = 0; ci < m_num_components; ci++)
{
if (last_bitpos[ci][0] < 0)
ERREXIT(J_MESSAGE_CODE.JERR_MISSING_DATA);
}
}
else
{
for (int ci = 0; ci < m_num_components; ci++)
{
if (!component_sent[ci])
ERREXIT(J_MESSAGE_CODE.JERR_MISSING_DATA);
}
}
}