Ejemplo n.º 1
0
        public static int Read(this Stream stream, Span <byte> buffer)
        {
            using var buff = new PoolArray <byte>(buffer.Length);

            int cb = stream.Read(buff.Array, 0, buff.Length);

            buff.Array.AsSpan(0, cb).CopyTo(buffer);

            return(cb);
        }
Ejemplo n.º 2
0
        public void Quantize(Span <byte> image, Span <byte> outbuff, nint width, nint height, nint instride, nint outstride)
        {
            var nc = (Span <int>) stackalloc int[] { 0, 0, 0, 0, 0, 0, 0, 0 };

            getNodeCounts(nc);

            uint level        = leafLevel;
            int  targetColors = maxPaletteSize - getReservedCount();

            for (uint i = 1; i < leafLevel; i++)
            {
                if (nc[(int)i] > targetColors)
                {
                    level = i;
                    break;
                }
            }

            fixed(OctreeNode *ptree = MemoryMarshal.Cast <byte, OctreeNode>(nodeBuffer))
            fixed(float *igt = &LookupTables.SrgbInverseGamma[0])
            {
                float ftpix = getPixelCount();

                for (nuint i = 0; i < 8; i++)
                {
                    convertNodes(ptree, igt, ptree + i, 0, level, ftpix);
                }

                leafLevel = level;
            }

            int histogramColors = nc[(int)level];

            if (histogramColors > targetColors)
            {
                var   listBuffer     = BufferPool.Rent(sizeof(ReducibleNode) * histogramColors);
                nuint reducibleCount = 0;

                fixed(OctreeNode *ptree = MemoryMarshal.Cast <byte, OctreeNode>(nodeBuffer))
                fixed(ReducibleNode * pweights = MemoryMarshal.Cast <byte, ReducibleNode>(listBuffer))
                fixed(float *gt = &LookupTables.SrgbGamma[0])
                {
                    for (nuint i = 0; i < 8; i++)
                    {
                        addReducibleNodes(ptree, pweights, gt, ptree + i, ref reducibleCount, 0, leafLevel - 1);
                    }
                }

                var weights     = MemoryMarshal.Cast <byte, ReducibleNode>(listBuffer).Slice(0, (int)reducibleCount);
                int reduceCount = histogramColors - targetColors;

#if SPAN_SORT
                weights.Sort();
                finalReduce(weights.Slice(0, reduceCount));
#else
                using var buff = new PoolArray <ReducibleNode>(maxHistogramSize);
                weights.CopyTo(buff.Array);

                Array.Sort(buff.Array, 0, weights.Length);
                finalReduce(buff.Array.AsSpan(0, reduceCount));
#endif
            }

            bool  dither   = isSubsampled || histogramColors > maxPaletteSize;
            nuint nextFree = makePaletteMap(level);

            var pbuff = BufferPool.Rent(((int)width + 2) * 16, true);
            pbuff.AsSpan().Clear();

            fixed(byte *pimage = image, poutbuff = outbuff, perrbuff = pbuff.AsSpan())
            fixed(uint *pilut        = &LookupTables.OctreeIndexTable[0])
            fixed(uint *ppal         = MemoryMarshal.Cast <byte, uint>(palBuffer))
            fixed(OctreeNode * ptree = MemoryMarshal.Cast <byte, OctreeNode>(nodeBuffer))
            {
                for (nint y = 0; y < height; y++)
                {
                    byte *pline    = pimage + y * instride;
                    byte *poutline = poutbuff + y * outstride;
                    int * perrline = (int *)perrbuff + 4;

                    if (!dither)
                    {
                        remap(pline, poutline, pilut, ptree, ppal, ref nextFree, width);
                    }
#if HWINTRINSICS
                    else if (Sse2.IsSupported)
                    {
                        remapDitherSse2(pline, perrline, poutline, pilut, ptree, ppal, ref nextFree, width);
                    }
#endif
                    else
                    {
                        remapDitherScalar(pline, perrline, poutline, pilut, ptree, ppal, ref nextFree, width);
                    }
                }
            }

            BufferPool.Return(pbuff);
        }