diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index f8be0f6cc..b18845aaa 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -178,7 +178,7 @@ namespace ImageSharp.Formats
///
/// Thrown if the stream does not contain and end chunk.
///
- ///
+ ///
/// Thrown if the image is larger than the maximum allowable size.
///
/// The decoded image
@@ -189,7 +189,6 @@ namespace ImageSharp.Formats
this.currentStream = stream;
this.currentStream.Skip(8);
Image image = null;
- PixelAccessor pixels = null;
try
{
using (var deframeStream = new ZlibInflateStream(this.currentStream))
@@ -211,11 +210,11 @@ namespace ImageSharp.Formats
case PngChunkTypes.Data:
if (image == null)
{
- this.InitializeImage(metadata, out image, out pixels);
+ this.InitializeImage(metadata, out image);
}
deframeStream.AllocateNewBytes(currentChunk.Length);
- this.ReadScanlines(deframeStream.CompressedStream, pixels);
+ this.ReadScanlines(deframeStream.CompressedStream, image);
stream.Read(this.crcBuffer, 0, 4);
break;
case PngChunkTypes.Palette:
@@ -252,7 +251,6 @@ namespace ImageSharp.Formats
}
finally
{
- pixels?.Dispose();
this.scanline?.Dispose();
this.previousScanline?.Dispose();
}
@@ -324,8 +322,7 @@ namespace ImageSharp.Formats
/// The type the pixels will be
/// The metadata information for the image
/// The image that we will populate
- /// The pixel accessor
- private void InitializeImage(ImageMetaData metadata, out Image image, out PixelAccessor pixels)
+ private void InitializeImage(ImageMetaData metadata, out Image image)
where TPixel : struct, IPixel
{
if (this.header.Width > Image.MaxWidth || this.header.Height > Image.MaxHeight)
@@ -334,7 +331,6 @@ namespace ImageSharp.Formats
}
image = new Image(this.configuration, this.header.Width, this.header.Height, metadata);
- pixels = image.Lock();
this.bytesPerPixel = this.CalculateBytesPerPixel();
this.bytesPerScanline = this.CalculateScanlineLength(this.header.Width) + 1;
this.bytesPerSample = 1;
@@ -398,17 +394,17 @@ namespace ImageSharp.Formats
///
/// The pixel format.
/// The containing data.
- /// The pixel data.
- private void ReadScanlines(Stream dataStream, PixelAccessor pixels)
+ /// The pixel data.
+ private void ReadScanlines(Stream dataStream, Image image)
where TPixel : struct, IPixel
{
if (this.header.InterlaceMethod == PngInterlaceMode.Adam7)
{
- this.DecodeInterlacedPixelData(dataStream, pixels);
+ this.DecodeInterlacedPixelData(dataStream, image);
}
else
{
- this.DecodePixelData(dataStream, pixels);
+ this.DecodePixelData(dataStream, image);
}
}
@@ -417,8 +413,8 @@ namespace ImageSharp.Formats
///
/// The pixel format.
/// The compressed pixel data stream.
- /// The image pixel accessor.
- private void DecodePixelData(Stream compressedStream, PixelAccessor pixels)
+ /// The image to decode to.
+ private void DecodePixelData(Stream compressedStream, Image image)
where TPixel : struct, IPixel
{
while (this.currentRow < this.header.Height)
@@ -462,7 +458,7 @@ namespace ImageSharp.Formats
throw new ImageFormatException("Unknown filter type.");
}
- this.ProcessDefilteredScanline(this.scanline.Array, pixels);
+ this.ProcessDefilteredScanline(this.scanline.Array, image);
Swap(ref this.scanline, ref this.previousScanline);
this.currentRow++;
@@ -475,8 +471,8 @@ namespace ImageSharp.Formats
///
/// The pixel format.
/// The compressed pixel data stream.
- /// The image pixel accessor.
- private void DecodeInterlacedPixelData(Stream compressedStream, PixelAccessor pixels)
+ /// The current image.
+ private void DecodeInterlacedPixelData(Stream compressedStream, Image image)
where TPixel : struct, IPixel
{
while (true)
@@ -537,7 +533,8 @@ namespace ImageSharp.Formats
throw new ImageFormatException("Unknown filter type.");
}
- this.ProcessInterlacedDefilteredScanline(this.scanline.Array, this.currentRow, pixels, Adam7FirstColumn[this.pass], Adam7ColumnIncrement[this.pass]);
+ Span rowSpan = image.GetRowSpan(this.currentRow);
+ this.ProcessInterlacedDefilteredScanline(this.scanline.Array, rowSpan, Adam7FirstColumn[this.pass], Adam7ColumnIncrement[this.pass]);
Swap(ref this.scanline, ref this.previousScanline);
@@ -561,12 +558,12 @@ namespace ImageSharp.Formats
///
/// The pixel format.
/// The de-filtered scanline
- /// The image pixels
- private void ProcessDefilteredScanline(byte[] defilteredScanline, PixelAccessor pixels)
+ /// The image
+ private void ProcessDefilteredScanline(byte[] defilteredScanline, Image pixels)
where TPixel : struct, IPixel
{
var color = default(TPixel);
- Span pixelBuffer = pixels.GetRowSpan(this.currentRow);
+ Span rowSpan = pixels.GetRowSpan(this.currentRow);
var scanlineBuffer = new Span(defilteredScanline, 1);
switch (this.PngColorType)
@@ -578,7 +575,7 @@ namespace ImageSharp.Formats
{
byte intensity = (byte)(newScanline1[x] * factor);
color.PackFromBytes(intensity, intensity, intensity, 255);
- pixels[x, this.currentRow] = color;
+ rowSpan[x] = color;
}
break;
@@ -593,26 +590,26 @@ namespace ImageSharp.Formats
byte alpha = defilteredScanline[offset + this.bytesPerSample];
color.PackFromBytes(intensity, intensity, intensity, alpha);
- pixels[x, this.currentRow] = color;
+ rowSpan[x] = color;
}
break;
case PngColorType.Palette:
- this.ProcessScanlineFromPalette(defilteredScanline, pixels);
+ this.ProcessScanlineFromPalette(defilteredScanline, rowSpan);
break;
case PngColorType.Rgb:
- PixelOperations.Instance.PackFromXyzBytes(scanlineBuffer, pixelBuffer, this.header.Width);
+ PixelOperations.Instance.PackFromXyzBytes(scanlineBuffer, rowSpan, this.header.Width);
break;
case PngColorType.RgbWithAlpha:
- PixelOperations.Instance.PackFromXyzwBytes(scanlineBuffer, pixelBuffer, this.header.Width);
+ PixelOperations.Instance.PackFromXyzwBytes(scanlineBuffer, rowSpan, this.header.Width);
break;
}
@@ -623,8 +620,8 @@ namespace ImageSharp.Formats
///
/// The type of pixel we are expanding to
/// The scanline
- /// The output pixels
- private void ProcessScanlineFromPalette(byte[] defilteredScanline, PixelAccessor pixels)
+ /// Thecurrent output image row
+ private void ProcessScanlineFromPalette(byte[] defilteredScanline, Span row)
where TPixel : struct, IPixel
{
byte[] newScanline = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth);
@@ -654,7 +651,7 @@ namespace ImageSharp.Formats
color.PackFromBytes(0, 0, 0, 0);
}
- pixels[x, this.currentRow] = color;
+ row[x] = color;
}
}
else
@@ -669,7 +666,7 @@ namespace ImageSharp.Formats
byte b = palette[pixelOffset + 2];
color.PackFromBytes(r, g, b, 255);
- pixels[x, this.currentRow] = color;
+ row[x] = color;
}
}
}
@@ -679,11 +676,10 @@ namespace ImageSharp.Formats
///
/// The pixel format.
/// The de-filtered scanline
- /// The current image row.
- /// The image pixels
+ /// The current image row.
/// The column start index. Always 0 for none interlaced images.
/// The column increment. Always 1 for none interlaced images.
- private void ProcessInterlacedDefilteredScanline(byte[] defilteredScanline, int row, PixelAccessor pixels, int pixelOffset = 0, int increment = 1)
+ private void ProcessInterlacedDefilteredScanline(byte[] defilteredScanline, Span rowSpan, int pixelOffset = 0, int increment = 1)
where TPixel : struct, IPixel
{
var color = default(TPixel);
@@ -697,7 +693,7 @@ namespace ImageSharp.Formats
{
byte intensity = (byte)(newScanline1[o] * factor);
color.PackFromBytes(intensity, intensity, intensity, 255);
- pixels[x, row] = color;
+ rowSpan[x] = color;
}
break;
@@ -710,7 +706,7 @@ namespace ImageSharp.Formats
byte alpha = defilteredScanline[o + this.bytesPerSample];
color.PackFromBytes(intensity, intensity, intensity, alpha);
- pixels[x, row] = color;
+ rowSpan[x] = color;
}
break;
@@ -742,7 +738,7 @@ namespace ImageSharp.Formats
color.PackFromBytes(0, 0, 0, 0);
}
- pixels[x, row] = color;
+ rowSpan[x] = color;
}
}
else
@@ -757,7 +753,7 @@ namespace ImageSharp.Formats
byte b = this.palette[offset + 2];
color.PackFromBytes(r, g, b, 255);
- pixels[x, row] = color;
+ rowSpan[x] = color;
}
}
@@ -772,7 +768,7 @@ namespace ImageSharp.Formats
byte b = defilteredScanline[o + (2 * this.bytesPerSample)];
color.PackFromBytes(r, g, b, 255);
- pixels[x, row] = color;
+ rowSpan[x] = color;
}
break;
@@ -787,7 +783,7 @@ namespace ImageSharp.Formats
byte a = defilteredScanline[o + (3 * this.bytesPerSample)];
color.PackFromBytes(r, g, b, a);
- pixels[x, row] = color;
+ rowSpan[x] = color;
}
break;
diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
index 0482b2691..3fcf1fc81 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
@@ -220,11 +220,7 @@ namespace ImageSharp.Formats
this.WritePhysicalChunk(stream, image);
this.WriteGammaChunk(stream);
- using (PixelAccessor pixels = image.Lock())
- {
- this.WriteDataChunks(pixels, stream);
- }
-
+ this.WriteDataChunks(image, stream);
this.WriteEndChunk(stream);
stream.Flush();
}
@@ -302,9 +298,8 @@ namespace ImageSharp.Formats
/// Collects a row of grayscale pixels.
///
/// The pixel format.
- /// The image pixels accessor.
- /// The row index.
- private void CollectGrayscaleBytes(PixelAccessor pixels, int row)
+ /// The image row span.
+ private void CollectGrayscaleBytes(Span rowSpan)
where TPixel : struct, IPixel
{
byte[] rawScanlineArray = this.rawScanline.Array;
@@ -316,7 +311,7 @@ namespace ImageSharp.Formats
// Convert the color to YCbCr and store the luminance
// Optionally store the original color alpha.
int offset = x * this.bytesPerPixel;
- pixels[x, row].ToXyzwBytes(this.chunkTypeBuffer, 0);
+ rowSpan[x].ToXyzwBytes(this.chunkTypeBuffer, 0);
byte luminance = (byte)((0.299F * this.chunkTypeBuffer[0]) + (0.587F * this.chunkTypeBuffer[1]) + (0.114F * this.chunkTypeBuffer[2]));
for (int i = 0; i < this.bytesPerPixel; i++)
@@ -337,13 +332,10 @@ namespace ImageSharp.Formats
/// Collects a row of true color pixel data.
///
/// The pixel format.
- /// The image pixel accessor.
- /// The row index.
- private void CollecTPixelBytes(PixelAccessor pixels, int row)
+ /// The row span.
+ private void CollecTPixelBytes(Span rowSpan)
where TPixel : struct, IPixel
{
- Span rowSpan = pixels.GetRowSpan(row);
-
if (this.bytesPerPixel == 4)
{
PixelOperations.Instance.ToXyzwBytes(rowSpan, this.rawScanline, this.width);
@@ -359,10 +351,10 @@ namespace ImageSharp.Formats
/// Each scanline is encoded in the most optimal manner to improve compression.
///
/// The pixel format.
- /// The image pixel accessor.
+ /// The row span.
/// The row.
/// The
- private Buffer EncodePixelRow(PixelAccessor pixels, int row)
+ private Buffer EncodePixelRow(Span rowSpan, int row)
where TPixel : struct, IPixel
{
switch (this.pngColorType)
@@ -372,10 +364,10 @@ namespace ImageSharp.Formats
break;
case PngColorType.Grayscale:
case PngColorType.GrayscaleWithAlpha:
- this.CollectGrayscaleBytes(pixels, row);
+ this.CollectGrayscaleBytes(rowSpan);
break;
default:
- this.CollecTPixelBytes(pixels, row);
+ this.CollecTPixelBytes(rowSpan);
break;
}
@@ -637,17 +629,17 @@ namespace ImageSharp.Formats
/// Writes the pixel information to the stream.
///
/// The pixel format.
- /// The pixel accessor.
+ /// The image.
/// The stream.
- private void WriteDataChunks(PixelAccessor pixels, Stream stream)
+ private void WriteDataChunks(Image pixels, Stream stream)
where TPixel : struct, IPixel
{
this.bytesPerScanline = this.width * this.bytesPerPixel;
int resultLength = this.bytesPerScanline + 1;
- this.previousScanline = new Buffer(this.bytesPerScanline);
- this.rawScanline = new Buffer(this.bytesPerScanline);
- this.result = new Buffer(resultLength);
+ this.previousScanline = Buffer.CreateClean(this.bytesPerScanline);
+ this.rawScanline = Buffer.CreateClean(this.bytesPerScanline);
+ this.result = Buffer.CreateClean(resultLength);
if (this.pngColorType != PngColorType.Palette)
{
@@ -667,7 +659,7 @@ namespace ImageSharp.Formats
{
for (int y = 0; y < this.height; y++)
{
- Buffer r = this.EncodePixelRow(pixels, y);
+ Buffer r = this.EncodePixelRow(pixels.GetRowSpan(y), y);
deflateStream.Write(r.Array, 0, resultLength);
Swap(ref this.rawScanline, ref this.previousScanline);