private static byte[] ToScanlines(Image image) { byte[] data = new byte[(image.Width * image.Height * 4) + image.Height]; int RowLength = (image.Width * 4) + 1; Parallel.For(0, image.Width, x => { int dataOffset = (x * 4) + 1; int PixelOffset = x; data[dataOffset] = image.Pixels[PixelOffset].Red; data[dataOffset + 1] = image.Pixels[PixelOffset].Green; data[dataOffset + 2] = image.Pixels[PixelOffset].Blue; data[dataOffset + 3] = image.Pixels[PixelOffset].Alpha; data[0] = 0; for (int y = 1; y < image.Height; ++y) { dataOffset = (y * RowLength) + (x * 4) + 1; PixelOffset = (image.Width * y) + x; int AbovePixelOffset = (image.Width * (y - 1)) + x; data[dataOffset] = (byte)(image.Pixels[PixelOffset].Red - image.Pixels[AbovePixelOffset].Red); data[dataOffset + 1] = (byte)(image.Pixels[PixelOffset].Green - image.Pixels[AbovePixelOffset].Green); data[dataOffset + 2] = (byte)(image.Pixels[PixelOffset].Blue - image.Pixels[AbovePixelOffset].Blue); data[dataOffset + 3] = (byte)(image.Pixels[PixelOffset].Alpha - image.Pixels[AbovePixelOffset].Alpha); data[y * RowLength] = 2; } }); using (MemoryStream TempMemoryStream = new MemoryStream()) { using (ZlibDeflateStream TempDeflateStream = new ZlibDeflateStream(TempMemoryStream, 6)) { TempDeflateStream.Write(data, 0, data.Length); } return(TempMemoryStream.ToArray()); } }
/// <summary> /// Writes the pixel information to the stream. /// </summary> /// <typeparam name="TPixel">The pixel format.</typeparam> /// <param name="pixels">The image.</param> /// <param name="stream">The stream.</param> private void WriteDataChunks <TPixel>(ImageFrame <TPixel> pixels, Stream stream) where TPixel : struct, IPixel <TPixel> { this.bytesPerScanline = this.width * this.bytesPerPixel; int resultLength = this.bytesPerScanline + 1; this.previousScanline = this.memoryManager.AllocateCleanManagedByteBuffer(this.bytesPerScanline); this.rawScanline = this.memoryManager.AllocateCleanManagedByteBuffer(this.bytesPerScanline); this.result = this.memoryManager.AllocateCleanManagedByteBuffer(resultLength); if (this.pngColorType != PngColorType.Palette) { this.sub = this.memoryManager.AllocateCleanManagedByteBuffer(resultLength); this.up = this.memoryManager.AllocateCleanManagedByteBuffer(resultLength); this.average = this.memoryManager.AllocateCleanManagedByteBuffer(resultLength); this.paeth = this.memoryManager.AllocateCleanManagedByteBuffer(resultLength); } byte[] buffer; int bufferLength; MemoryStream memoryStream = null; try { memoryStream = new MemoryStream(); using (var deflateStream = new ZlibDeflateStream(memoryStream, this.compressionLevel)) { for (int y = 0; y < this.height; y++) { IManagedByteBuffer r = this.EncodePixelRow(pixels.GetPixelRowSpan(y), y); deflateStream.Write(r.Array, 0, resultLength); IManagedByteBuffer temp = this.rawScanline; this.rawScanline = this.previousScanline; this.previousScanline = temp; } } 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); } }
private void WriteDataChunks(Stream stream, Image image) { byte[] pixels = image.Pixels; byte[] data = new byte[image.Width * image.Height * 4 + image.Height]; int rowLength = image.Width * 4 + 1; for (int y = 0; y < image.Height; y++) { byte compression = 0; if (y > 0) { compression = 2; } data[y * rowLength] = compression; for (int x = 0; x < image.Width; x++) { // Calculate the offset for the new array. int dataOffset = y * rowLength + x * 4 + 1; // Calculate the offset for the original pixel array. int pixelOffset = (y * image.Width + x) * 4; data[dataOffset + 0] = pixels[pixelOffset + 2]; data[dataOffset + 1] = pixels[pixelOffset + 1]; data[dataOffset + 2] = pixels[pixelOffset + 0]; data[dataOffset + 3] = pixels[pixelOffset + 3]; if (y > 0) { int lastOffset = ((y - 1) * image.Width + x) * 4; data[dataOffset + 0] -= pixels[lastOffset + 2]; data[dataOffset + 1] -= pixels[lastOffset + 1]; data[dataOffset + 2] -= pixels[lastOffset + 0]; data[dataOffset + 3] -= pixels[lastOffset + 3]; } } } byte[] buffer = null; int bufferLength = 0; MemoryStream memoryStream = null; try { memoryStream = new MemoryStream(); using (var zStream = new ZlibDeflateStream(memoryStream, 6)) { zStream.Write(data, 0, data.Length); } bufferLength = (int)memoryStream.Length; buffer = memoryStream.ToArray(); } finally { if (memoryStream != null) { 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; } WriteChunk(stream, PngChunkTypes.Data, buffer, i * MaxBlockSize, length); } }
private void WriteDataChunks(Stream stream, IPixelAccessor pixels, QuantizedImage quantized) { byte[] data; int imageWidth = pixels.Width; int imageHeight = pixels.Height; if (Quality <= 256) { int rowLength = imageWidth + 1; data = new byte[rowLength * imageHeight]; Parallel.For(0, imageHeight, Bootstrapper.instance.ParallelOptions, y => { int dataOffset = (y * rowLength); byte compression = 0; if (y > 0) { compression = 2; } data[dataOffset++] = compression; for (int x = 0; x < imageWidth; x++) { data[dataOffset++] = quantized.Pixels[(y * imageWidth) + x]; if (y > 0) { data[dataOffset - 1] -= quantized.Pixels[((y - 1) * imageWidth) + x]; } } }); } else { data = new byte[(imageWidth * imageHeight * 4) + pixels.Height]; int rowLength = (imageWidth * 4) + 1; Parallel.For(0, imageHeight, Bootstrapper.instance.ParallelOptions, y => { byte compression = 0; if (y > 0) { compression = 2; } data[y * rowLength] = compression; for (int x = 0; x < imageWidth; x++) { byte[] color = pixels[x, y].ToBytes(); int dataOffset = (y * rowLength) + (x * 4) + 1; data[dataOffset] = color[0]; data[dataOffset + 1] = color[1]; data[dataOffset + 2] = color[2]; data[dataOffset + 3] = color[3]; if (y > 0) { color = pixels[x, y - 1].ToBytes(); data[dataOffset] -= color[0]; data[dataOffset + 1] -= color[1]; data[dataOffset + 2] -= color[2]; data[dataOffset + 3] -= color[3]; } } }); } byte[] buffer; int bufferLength; MemoryStream memoryStream = null; try{ memoryStream = new MemoryStream(); using (ZlibDeflateStream deflateStream = new ZlibDeflateStream(memoryStream, 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; } WriteChunk(stream, PngChunkTypes.Data, buffer, i * maxBlockSize, length); } }