/// <summary> /// Writes the pixel information to the stream. /// TODO: This is WHACK! We should be able to do this without creating yet another array. /// </summary> /// <param name="stream">The stream.</param> private void WriteDataChunks(Stream stream) { byte[] data = this.EncodePixelData(); byte[] buffer; int bufferLength; MemoryStream memoryStream = null; try { memoryStream = new MemoryStream(); using (ZlibDeflateStream deflateStream = new ZlibDeflateStream(memoryStream, this.CompressionLevel)) { deflateStream.Write(data, 0, data.Length); } bufferLength = (int)memoryStream.Length; buffer = memoryStream.ToArray(); } finally { memoryStream?.Dispose(); } int numChunks = bufferLength / MaxBlockSize; if (bufferLength % MaxBlockSize != 0) { numChunks++; } for (int i = 0; i < numChunks; i++) { int length = bufferLength - (i * MaxBlockSize); if (length > MaxBlockSize) { length = MaxBlockSize; } this.WriteChunk(stream, PngChunkTypes.Data, buffer, i * MaxBlockSize, length); } }
/// <summary> /// Writes the pixel information to the stream. /// </summary> /// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam> /// <param name="pixels">The pixel accessor.</param> /// <param name="stream">The stream.</param> private void WriteDataChunks <TColor, TPacked>(PixelAccessor <TColor, TPacked> pixels, Stream stream) where TColor : struct, IPackedPixel <TPacked> where TPacked : struct, IEquatable <TPacked> { int bytesPerScanline = this.width * this.bytesPerPixel; byte[] previousScanline = new byte[bytesPerScanline]; byte[] rawScanline = new byte[bytesPerScanline]; int resultLength = bytesPerScanline + 1; byte[] result = new byte[resultLength]; if (this.PngColorType != PngColorType.Palette) { this.sub = new byte[resultLength]; this.up = new byte[resultLength]; this.average = new byte[resultLength]; this.paeth = new byte[resultLength]; } byte[] buffer; int bufferLength; MemoryStream memoryStream = null; try { memoryStream = new MemoryStream(); using (ZlibDeflateStream deflateStream = new ZlibDeflateStream(memoryStream, this.CompressionLevel)) { for (int y = 0; y < this.height; y++) { deflateStream.Write(this.EncodePixelRow(pixels, y, previousScanline, rawScanline, result), 0, resultLength); Swap(ref rawScanline, ref previousScanline); } } buffer = memoryStream.ToArray(); bufferLength = buffer.Length; } finally { memoryStream?.Dispose(); } // Store the chunks in repeated 64k blocks. // This reduces the memory load for decoding the image for many decoders. int numChunks = bufferLength / MaxBlockSize; if (bufferLength % MaxBlockSize != 0) { numChunks++; } for (int i = 0; i < numChunks; i++) { int length = bufferLength - (i * MaxBlockSize); if (length > MaxBlockSize) { length = MaxBlockSize; } this.WriteChunk(stream, PngChunkTypes.Data, buffer, i * MaxBlockSize, length); } }
/// <summary> /// Writes the pixel information to the stream. /// </summary> /// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam> /// <param name="pixels">The pixel accessor.</param> /// <param name="stream">The stream.</param> private void WriteDataChunks <TColor, TPacked>(PixelAccessor <TColor, TPacked> pixels, Stream stream) where TColor : struct, IPackedPixel <TPacked> where TPacked : struct { int bytesPerScanline = this.width * this.bytesPerPixel; byte[] previousScanline = ArrayPool <byte> .Shared.Rent(bytesPerScanline); byte[] rawScanline = ArrayPool <byte> .Shared.Rent(bytesPerScanline); int resultLength = bytesPerScanline + 1; byte[] result = ArrayPool <byte> .Shared.Rent(resultLength); byte[] buffer; int bufferLength; MemoryStream memoryStream = null; try { memoryStream = new MemoryStream(); using (ZlibDeflateStream deflateStream = new ZlibDeflateStream(memoryStream, this.CompressionLevel)) { for (int y = 0; y < this.height; y++) { this.EncodePixelRow(pixels, y, previousScanline, rawScanline, result, bytesPerScanline); deflateStream.Write(result, 0, resultLength); // Do a bit of shuffling; byte[] tmp = rawScanline; rawScanline = previousScanline; previousScanline = tmp; } deflateStream.Flush(); bufferLength = (int)memoryStream.Length; buffer = memoryStream.ToArray(); } } finally { ArrayPool <byte> .Shared.Return(previousScanline); ArrayPool <byte> .Shared.Return(rawScanline); ArrayPool <byte> .Shared.Return(result); memoryStream?.Dispose(); } // Store the chunks in repeated 64k blocks. // This reduces the memory load for decoding the image for many decoders. int numChunks = bufferLength / MaxBlockSize; if (bufferLength % MaxBlockSize != 0) { numChunks++; } for (int i = 0; i < numChunks; i++) { int length = bufferLength - (i * MaxBlockSize); if (length > MaxBlockSize) { length = MaxBlockSize; } this.WriteChunk(stream, PngChunkTypes.Data, buffer, i * MaxBlockSize, length); } }