コード例 #1
0
        private static void AddSingleLiteral(uint pixel, bool useColorCache, ColorCache colorCache, Vp8LBackwardRefs refs)
        {
            PixOrCopy v;

            if (useColorCache)
            {
                int key = colorCache.GetIndex(pixel);
                if (colorCache.Lookup(key) == pixel)
                {
                    v = PixOrCopy.CreateCacheIdx(key);
                }
                else
                {
                    v = PixOrCopy.CreateLiteral(pixel);
                    colorCache.Set((uint)key, pixel);
                }
            }
            else
            {
                v = PixOrCopy.CreateLiteral(pixel);
            }

            refs.Add(v);
        }
コード例 #2
0
        public void DecodeImageData(Vp8LDecoder decoder, Span <uint> pixelData)
        {
            int               lastPixel       = 0;
            int               width           = decoder.Width;
            int               height          = decoder.Height;
            int               row             = lastPixel / width;
            int               col             = lastPixel % width;
            const int         lenCodeLimit    = WebpConstants.NumLiteralCodes + WebpConstants.NumLengthCodes;
            int               colorCacheSize  = decoder.Metadata.ColorCacheSize;
            ColorCache        colorCache      = decoder.Metadata.ColorCache;
            int               colorCacheLimit = lenCodeLimit + colorCacheSize;
            int               mask            = decoder.Metadata.HuffmanMask;
            Span <HTreeGroup> hTreeGroup      = GetHTreeGroupForPos(decoder.Metadata, col, row);

            int totalPixels   = width * height;
            int decodedPixels = 0;
            int lastCached    = decodedPixels;

            while (decodedPixels < totalPixels)
            {
                int code;
                if ((col & mask) == 0)
                {
                    hTreeGroup = GetHTreeGroupForPos(decoder.Metadata, col, row);
                }

                if (hTreeGroup[0].IsTrivialCode)
                {
                    pixelData[decodedPixels] = hTreeGroup[0].LiteralArb;
                    this.AdvanceByOne(ref col, ref row, width, colorCache, ref decodedPixels, pixelData, ref lastCached);
                    continue;
                }

                this.bitReader.FillBitWindow();
                if (hTreeGroup[0].UsePackedTable)
                {
                    code = (int)this.ReadPackedSymbols(hTreeGroup, pixelData, decodedPixels);
                    if (this.bitReader.IsEndOfStream())
                    {
                        break;
                    }

                    if (code == PackedNonLiteralCode)
                    {
                        this.AdvanceByOne(ref col, ref row, width, colorCache, ref decodedPixels, pixelData, ref lastCached);
                        continue;
                    }
                }
                else
                {
                    code = (int)this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Green]);
                }

                if (this.bitReader.IsEndOfStream())
                {
                    break;
                }

                // Literal
                if (code < WebpConstants.NumLiteralCodes)
                {
                    if (hTreeGroup[0].IsTrivialLiteral)
                    {
                        pixelData[decodedPixels] = hTreeGroup[0].LiteralArb | ((uint)code << 8);
                    }
                    else
                    {
                        uint red = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Red]);
                        this.bitReader.FillBitWindow();
                        uint blue  = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Blue]);
                        uint alpha = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Alpha]);
                        if (this.bitReader.IsEndOfStream())
                        {
                            break;
                        }

                        pixelData[decodedPixels] = (uint)(((byte)alpha << 24) | ((byte)red << 16) | ((byte)code << 8) | (byte)blue);
                    }

                    this.AdvanceByOne(ref col, ref row, width, colorCache, ref decodedPixels, pixelData, ref lastCached);
                }
                else if (code < lenCodeLimit)
                {
                    // Backward reference is used.
                    int  lengthSym  = code - WebpConstants.NumLiteralCodes;
                    int  length     = this.GetCopyLength(lengthSym);
                    uint distSymbol = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Dist]);
                    this.bitReader.FillBitWindow();
                    int distCode = this.GetCopyDistance((int)distSymbol);
                    int dist     = PlaneCodeToDistance(width, distCode);
                    if (this.bitReader.IsEndOfStream())
                    {
                        break;
                    }

                    CopyBlock(pixelData, decodedPixels, dist, length);
                    decodedPixels += length;
                    col           += length;
                    while (col >= width)
                    {
                        col -= width;
                        row++;
                    }

                    if ((col & mask) != 0)
                    {
                        hTreeGroup = GetHTreeGroupForPos(decoder.Metadata, col, row);
                    }

                    if (colorCache != null)
                    {
                        while (lastCached < decodedPixels)
                        {
                            colorCache.Insert(pixelData[lastCached]);
                            lastCached++;
                        }
                    }
                }
                else if (code < colorCacheLimit)
                {
                    // Color cache should be used.
                    int key = code - lenCodeLimit;
                    while (lastCached < decodedPixels)
                    {
                        colorCache.Insert(pixelData[lastCached]);
                        lastCached++;
                    }

                    pixelData[decodedPixels] = colorCache.Lookup(key);
                    this.AdvanceByOne(ref col, ref row, width, colorCache, ref decodedPixels, pixelData, ref lastCached);
                }
                else
                {
                    WebpThrowHelper.ThrowImageFormatException("Webp parsing error");
                }
            }
        }