Exemplo n.º 1
0
        /// <summary>
        /// Create the colormap.
        /// </summary>
        private void CreateColormap()
        {
            /* Select number of colors for each component */
            var total_colors = SelectNColors(m_Ncolors);

            /* Report selected color counts */
            if (m_cinfo.outColorComponents == 3)
            {
                m_cinfo.TraceMS(1, JMessageCode.JTRC_QUANT_3_NCOLORS, total_colors, m_Ncolors[0], m_Ncolors[1], m_Ncolors[2]);
            }
            else
            {
                m_cinfo.TraceMS(1, JMessageCode.JTRC_QUANT_NCOLORS, total_colors);
            }

            /* Allocate and fill in the colormap. */
            /* The colors are ordered in the map in standard row-major order, */
            /* i.e. rightmost (highest-indexed) color changes most rapidly. */
            var colormap = JpegCommonStruct.AllocJpegSamples(total_colors, m_cinfo.outColorComponents);

            /* blksize is number of adjacent repeated entries for a component */
            /* blkdist is distance between groups of identical entries for a component */
            var blkdist = total_colors;

            for (var i = 0; i < m_cinfo.outColorComponents; i++)
            {
                /* fill in colormap entries for i'th color component */
                var nci     = m_Ncolors[i]; /* # of distinct values for this color */
                var blksize = blkdist / nci;
                for (var j = 0; j < nci; j++)
                {
                    /* Compute j'th output value (out of nci) for component */
                    var val = OutputValue(j, nci - 1);

                    /* Fill in all colormap entries that have this value of this component */
                    for (var ptr = j * blksize; ptr < total_colors; ptr += blkdist)
                    {
                        /* fill in blksize entries beginning at ptr */
                        for (var k = 0; k < blksize; k++)
                        {
                            colormap[i][ptr + k] = (byte)val;
                        }
                    }
                }

                /* blksize of this color is blkdist of next */
                blkdist = blksize;
            }

            /* Save the colormap in private storage,
             * where it will survive color quantization mode changes.
             */
            m_sv_colormap = colormap;
            m_sv_actual   = total_colors;
        }
Exemplo n.º 2
0
        /// <summary>
        /// This is the default resync_to_restart method for data source
        /// managers to use if they don't have any better approach.
        /// </summary>
        /// <param name="cinfo">An instance of <see cref="JpegDecompressStruct"/></param>
        /// <param name="desired">The desired</param>
        /// <returns><c>false</c> if suspension is required.</returns>
        /// <remarks><para>
        /// 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.<br/><br/>
        /// </para>
        /// <para>
        /// 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.<br/><br/>
        /// </para>
        /// <para>
        /// 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.<br/><br/>
        /// </para>
        /// <para>
        /// 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:<br/>
        /// 1. Simply discard the marker and let the entropy decoder resume at next
        /// byte of file.<br/>
        /// 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.)<br/>
        /// 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.<br/>
        /// </para>
        /// <para>
        /// #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).<br/>
        /// 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).<br/>
        /// 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.
        /// </para></remarks>
        public virtual bool ReSyncToRestart(JpegDecompressStruct cinfo, int desired)
        {
            if (cinfo is null)
            {
                throw new System.ArgumentNullException(nameof(cinfo));
            }
            /* Always put up a warning. */
            cinfo.WarnMS(JMessageCode.JWRN_MUST_RESYNC, cinfo.m_unreadMarker, desired);

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

                cinfo.TraceMS(4, JMessageCode.JTRC_RECOVERY_ACTION, cinfo.m_unreadMarker, action);

                switch (action)
                {
                case 1:
                    /* Discard marker and let entropy decoder resume processing. */
                    cinfo.m_unreadMarker = 0;
                    return(true);

                case 2:
                    /* Scan to the next marker, and repeat the decision loop. */
                    if (!cinfo.m_marker.NextMarker())
                    {
                        return(false);
                    }

                    break;

                case 3:
                    /* Return without advancing past this marker. */
                    /* Entropy decoder will be forced to process an empty segment. */
                    return(true);
                }
            }
        }