diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index b1517299b6..36307d9e91 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -185,12 +185,12 @@ namespace ImageSharp.Formats } else { - this.CollectColorBytes(image); + // this.CollectColorBytes(image); } this.WritePhysicalChunk(stream, image); this.WriteGammaChunk(stream); - this.WriteDataChunks(stream); + this.WriteDataChunks(image, stream); this.WriteEndChunk(stream); stream.Flush(); } @@ -299,29 +299,24 @@ namespace ImageSharp.Formats /// The pixel format. /// The packed format. uint, long, float. /// The image to encode. - private void CollectColorBytes(ImageBase image) + /// The row index. + /// The raw Scanline. + private void CollectColorBytes(ImageBase image, int row, byte[] rawScanline) where TColor : struct, IPackedPixel where TPacked : struct { - // Copy the pixels across from the image. - // TODO: This could be sped up more if we add a method to PixelAccessor that does this by row directly to a byte array. - this.pixelData = new byte[this.width * this.height * this.bytesPerPixel]; - int stride = this.width * this.bytesPerPixel; using (PixelAccessor pixels = image.Lock()) { int bpp = this.bytesPerPixel; - Parallel.For( - 0, - this.height, - Bootstrapper.Instance.ParallelOptions, - y => - { - for (int x = 0; x < this.width; x++) - { - int dataOffset = (y * stride) + (x * this.bytesPerPixel); - pixels[x, y].ToBytes(this.pixelData, dataOffset, bpp == 4 ? ComponentOrder.XYZW : ComponentOrder.XYZ); - } - }); + for (int x = 0; x < this.width; x++) + { + pixels[x, row].ToBytes(rawScanline, x * this.bytesPerPixel, bpp == 4 ? ComponentOrder.XYZW : ComponentOrder.XYZ); + } + + if (rawScanline.Any(x => x > 0)) + { + var t = rawScanline; + } } } @@ -329,14 +324,27 @@ namespace ImageSharp.Formats /// Encodes the pixel data line by line. /// Each scanline is encoded in the most optimal manner to improve compression. /// + /// The pixel format. + /// The packed format. uint, long, float. + /// The image to encode. /// The row. /// The previous scanline. /// The raw scanline. /// The number of bytes per scanline. /// The - private byte[] EncodePixelRow(int row, byte[] previousScanline, byte[] rawScanline, int bytesPerScanline) + private byte[] EncodePixelRow(ImageBase image, int row, byte[] previousScanline, byte[] rawScanline, int bytesPerScanline) + where TColor : struct, IPackedPixel + where TPacked : struct { - Buffer.BlockCopy(this.pixelData, row * bytesPerScanline, rawScanline, 0, bytesPerScanline); + if (this.PngColorType == PngColorType.Palette || this.PngColorType == PngColorType.Grayscale || this.PngColorType == PngColorType.GrayscaleWithAlpha) + { + Buffer.BlockCopy(this.pixelData, row * bytesPerScanline, rawScanline, 0, bytesPerScanline); + } + else + { + this.CollectColorBytes(image, row, rawScanline); + } + byte[] filteredScanline = this.GetOptimalFilteredScanline(rawScanline, previousScanline, bytesPerScanline, this.bytesPerPixel); return filteredScanline; @@ -571,8 +579,13 @@ namespace ImageSharp.Formats /// /// Writes the pixel information to the stream. /// + /// The pixel format. + /// The packed format. uint, long, float. + /// The image to encode. /// The stream. - private void WriteDataChunks(Stream stream) + private void WriteDataChunks(ImageBase image, Stream stream) + where TColor : struct, IPackedPixel + where TPacked : struct { int bytesPerScanline = this.width * this.bytesPerPixel; @@ -590,7 +603,7 @@ namespace ImageSharp.Formats { for (int y = 0; y < this.height; y++) { - byte[] data = this.EncodePixelRow(y, previousScanline, rawScanline, bytesPerScanline); + byte[] data = this.EncodePixelRow(image, y, previousScanline, rawScanline, bytesPerScanline); deflateStream.Write(data, 0, data.Length); deflateStream.Flush();