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); }
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); }