BitMiracle.LibJpeg.Classic.jpeg_compress_struct.validate_script C# (CSharp) Method

validate_script() private method

Verify that the scan script in scan_info[] is valid; also determine whether it uses progressive JPEG, and set progressive_mode.
private validate_script ( ) : void
return void
        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);
                }
            }
        }