BitMiracle.LibJpeg.Classic.jpeg_source_mgr.resync_to_restart C# (CSharp) Method

resync_to_restart() public method

This is the default resync_to_restart method for data source managers to use if they don't have any better approach.
That method assumes that no backtracking is possible. Some data source managers may be able to back up, or may have additional knowledge about the data which permits a more intelligent recovery strategy; such managers would presumably supply their own resync method.

read_restart_marker calls resync_to_restart if it finds a marker other than the restart marker it was expecting. (This code is *not* used unless a nonzero restart interval has been declared.) cinfo.unread_marker is the marker code actually found (might be anything, except 0 or FF). The desired restart marker number (0..7) is passed as a parameter.

This routine is supposed to apply whatever error recovery strategy seems appropriate in order to position the input stream to the next data segment. Note that cinfo.unread_marker is treated as a marker appearing before the current data-source input point; usually it should be reset to zero before returning.

This implementation is substantially constrained by wanting to treat the input as a data stream; this means we can't back up. Therefore, we have only the following actions to work with:
1. Simply discard the marker and let the entropy decoder resume at next byte of file.
2. Read forward until we find another marker, discarding intervening data. (In theory we could look ahead within the current bufferload, without having to discard data if we don't find the desired marker. This idea is not implemented here, in part because it makes behavior dependent on buffer size and chance buffer-boundary positions.)
3. Leave the marker unread (by failing to zero cinfo.unread_marker). This will cause the entropy decoder to process an empty data segment, inserting dummy zeroes, and then we will reprocess the marker.
#2 is appropriate if we think the desired marker lies ahead, while #3 is appropriate if the found marker is a future restart marker (indicating that we have missed the desired restart marker, probably because it got corrupted).
We apply #2 or #3 if the found marker is a restart marker no more than two counts behind or ahead of the expected one. We also apply #2 if the found marker is not a legal JPEG marker code (it's certainly bogus data). If the found marker is a restart marker more than 2 counts away, we do #1 (too much risk that the marker is erroneous; with luck we will be able to resync at some future point).
For any valid non-restart JPEG marker, we apply #3. This keeps us from overrunning the end of a scan. An implementation limited to single-scan files might find it better to apply #2 for markers other than EOI, since any other marker would have to be bogus data in that case.
public resync_to_restart ( jpeg_decompress_struct cinfo, int desired ) : bool
cinfo jpeg_decompress_struct An instance of
desired int The desired
return bool
        public virtual bool resync_to_restart(jpeg_decompress_struct cinfo, int desired)
        {
            /* Always put up a warning. */
            cinfo.WARNMS(J_MESSAGE_CODE.JWRN_MUST_RESYNC, cinfo.m_unread_marker, desired);

            /* Outer loop handles repeated decision after scanning forward. */
            int action = 1;
            for ( ; ; )
            {
                if (cinfo.m_unread_marker < (int)JPEG_MARKER.SOF0)
                {
                    /* invalid marker */
                    action = 2;
                }
                else if (cinfo.m_unread_marker < (int)JPEG_MARKER.RST0 ||
                    cinfo.m_unread_marker > (int)JPEG_MARKER.RST7)
                {
                    /* valid non-restart marker */
                    action = 3;
                }
                else
                {
                    if (cinfo.m_unread_marker == ((int)JPEG_MARKER.RST0 + ((desired + 1) & 7))
                        || cinfo.m_unread_marker == ((int)JPEG_MARKER.RST0 + ((desired + 2) & 7)))
                    {
                        /* one of the next two expected restarts */
                        action = 3;
                    }
                    else if (cinfo.m_unread_marker == ((int)JPEG_MARKER.RST0 + ((desired - 1) & 7)) ||
                        cinfo.m_unread_marker == ((int)JPEG_MARKER.RST0 + ((desired - 2) & 7)))
                    {
                        /* a prior restart, so advance */
                        action = 2;
                    }
                    else
                    {
                        /* desired restart or too far away */
                        action = 1;
                    }
                }

                cinfo.TRACEMS(4, J_MESSAGE_CODE.JTRC_RECOVERY_ACTION, cinfo.m_unread_marker, action);

                switch (action)
                {
                    case 1:
                        /* Discard marker and let entropy decoder resume processing. */
                        cinfo.m_unread_marker = 0;
                        return true;
                    case 2:
                        /* Scan to the next marker, and repeat the decision loop. */
                        if (!cinfo.m_marker.next_marker())
                            return false;
                        break;
                    case 3:
                        /* Return without advancing past this marker. */
                        /* Entropy decoder will be forced to process an empty segment. */
                        return true;
                }
            }
        }