示例#1
0
        private bool IsDuplicate(Bitmap32Bits bm,
                                 Dictionary <int, int> duplicateHashToIndex,
                                 int sourceIndex,
                                 out int duplicateIndex)
        {
            int x      = ItoX(sourceIndex);
            int y      = ItoY(sourceIndex);
            int width  = Math.Min(mBlockSize, bm.Width - x);
            int height = Math.Min(mBlockSize, bm.Height - y);

            int hash = bm.HashInt(x, y, width, height);

            if (duplicateHashToIndex.ContainsKey(hash))
            {
                // Possibly a match, but needs verification just in case there is a hash collison
                duplicateIndex = duplicateHashToIndex[hash];
                if (bm.IsMatch(x, y, width, height, bm, ItoX(duplicateIndex), ItoY(duplicateIndex)))
                {
                    return(true);
                }
                // Hash collision.  This is very rare.
                mHashCollisions++;
                duplicateIndex = 0;
                return(false);
            }
            // First time this block has been seen
            duplicateHashToIndex[hash] = sourceIndex;
            duplicateIndex             = 0;
            return(false);
        }
示例#2
0
        /// <summary>
        /// Score a frame, creating a list of blocks
        /// </summary>
        private void ScoreFrame(Bitmap32Bits frame,
                                bool disableDelta,
                                out List <Block> blocks,
                                out Dictionary <int, int> duplicates,
                                out int jpgCount,
                                out int pngCount)
        {
            blocks     = new List <Block>();
            duplicates = new Dictionary <int, int>();
            jpgCount   = 0;
            pngCount   = 0;

            var sourceIndex          = -1;
            var duplicateHashToIndex = new Dictionary <int, int>();

            for (int y = 0; y < frame.Height; y += mBlockSize)
            {
                for (int x = 0; x < frame.Width; x += mBlockSize)
                {
                    sourceIndex++;
                    Debug.Assert(ItoX(sourceIndex) == x);
                    Debug.Assert(ItoY(sourceIndex) == y);

                    // Skip clear blocks
                    int width  = Math.Min(mBlockSize, frame.Width - x);
                    int height = Math.Min(mBlockSize, frame.Height - y);
                    if (!disableDelta && frame.IsMatch(x, y, width, height, mBackground, x, y))
                    {
                        continue; // Nothing changed, skip it
                    }
                    frame.Copy(x, y, width, height, mBackground, x, y);

                    // Check for solid blocks
                    if (frame.IsSolid(x, y, width, height))
                    {
                        blocks.Add(new Block(sourceIndex, Score.Solid));
                        continue;
                    }
                    // Check for duplicates
                    int duplicateIndex;
                    if (IsDuplicate(frame, duplicateHashToIndex, sourceIndex, out duplicateIndex))
                    {
                        blocks.Add(new Block(sourceIndex, Score.Duplicate));
                        duplicates[sourceIndex] = duplicateIndex;
                        continue;
                    }
                    // Compression: SmartPNG, JPG, or PNG
                    bool usePng = mCompression == CompressionType.Png;
                    var  score  = Score.None;
                    if (mCompression == CompressionType.SmartPng && width >= 4 && height >= 4)
                    {
                        // SmartPng - Check to see if the block would compress well with PNG
                        var rleCount       = frame.RleCount(x, y, width, height);
                        var rleTotal       = (height - 1) * (width - 1);
                        var rleCompression = rleCount / (float)rleTotal;
                        score = (Score)((int)(rleCompression * 9.99) << (int)Score.ScoreShift) & Score.ScoreMask;
                        if (rleCompression > mPngCompressionThreshold)
                        {
                            if (!frame.LowFrequency(x, y, width, height))
                            {
                                usePng = true; // Good compression, not low frequency
                            }
                            else
                            {
                                score |= Score.LowFrequency;
                            }
                        }
                    }
                    blocks.Add(new Block(sourceIndex, score | (usePng ? Score.Png : Score.Jpg)));
                    if (usePng)
                    {
                        pngCount++;
                    }
                    else
                    {
                        jpgCount++;
                    }
                }
            }
            mDuplicates = duplicates.Count;
        }