Browse Source

pooling YCbCrImage contents

af/merge-core
antonfirsov 9 years ago
parent
commit
e6cd068115
  1. 26
      src/ImageSharp/Formats/Jpg/Components/Decoder/JpegPixelArea.cs
  2. 64
      src/ImageSharp/Formats/Jpg/Components/Decoder/YCbCrImage.cs
  3. 10
      src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs
  4. 2
      src/ImageSharp/Formats/Jpg/Utils/CleanPooler.cs

26
src/ImageSharp/Formats/Jpg/Components/Decoder/JpegPixelArea.cs

@ -25,7 +25,7 @@ namespace ImageSharp.Formats.Jpg
int size = width * height; int size = width * height;
//var pixels = ArrayPool<byte>.Shared.Rent(size); //var pixels = ArrayPool<byte>.Shared.Rent(size);
//Array.Clear(pixels, 0, size); //Array.Clear(pixels, 0, size);
var pixels = ArrayPoolManager<byte>.RentCleanArray(size); var pixels = CleanPooler<byte>.RentCleanArray(size);
return new JpegPixelArea(pixels, width, 0); return new JpegPixelArea(pixels, width, 0);
} }
@ -39,7 +39,7 @@ namespace ImageSharp.Formats.Jpg
public void ReturnPooled() public void ReturnPooled()
{ {
if (this.Pixels == null) return; if (this.Pixels == null) return;
ArrayPoolManager<byte>.ReturnArray(this.Pixels); CleanPooler<byte>.ReturnArray(this.Pixels);
this.Pixels = null; this.Pixels = null;
} }
@ -59,27 +59,7 @@ namespace ImageSharp.Formats.Jpg
/// Gets or sets the offset /// Gets or sets the offset
/// </summary> /// </summary>
public int Offset { get; private set; } public int Offset { get; private set; }
/// <summary>
/// Gets an image made up of a subset of the originals pixels.
/// </summary>
/// <param name="x">The x-coordinate of the image.</param>
/// <param name="y">The y-coordinate of the image.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <returns>
/// The <see cref="JpegPixelArea"/>.
/// </returns>
public JpegPixelArea Subimage(int x, int y, int width, int height)
{
return new JpegPixelArea
{
Stride = width,
Pixels = this.Pixels,
Offset = (y * this.Stride) + x
};
}
/// <summary> /// <summary>
/// Get the subarea that belongs to the given block indices /// Get the subarea that belongs to the given block indices
/// </summary> /// </summary>

64
src/ImageSharp/Formats/Jpg/Components/Decoder/YCbCrImage.cs

@ -5,12 +5,13 @@
namespace ImageSharp.Formats.Jpg namespace ImageSharp.Formats.Jpg
{ {
using System;
using System.Buffers; using System.Buffers;
/// <summary> /// <summary>
/// Represents an image made up of three color components (luminance, blue chroma, red chroma) /// Represents an image made up of three color components (luminance, blue chroma, red chroma)
/// </summary> /// </summary>
internal class YCbCrImage internal class YCbCrImage : IDisposable
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="YCbCrImage"/> class. /// Initializes a new instance of the <see cref="YCbCrImage"/> class.
@ -18,14 +19,16 @@ namespace ImageSharp.Formats.Jpg
/// <param name="width">The width.</param> /// <param name="width">The width.</param>
/// <param name="height">The height.</param> /// <param name="height">The height.</param>
/// <param name="ratio">The ratio.</param> /// <param name="ratio">The ratio.</param>
public YCbCrImage(int width, int height, YCbCrSubsampleRatio ratio) public YCbCrImage(int width, int height, YCbCrSubsampleRatio ratio, int yOffset, int cOffset)
{ {
int cw, ch; int cw, ch;
YCbCrSize(width, height, ratio, out cw, out ch); YCbCrSize(width, height, ratio, out cw, out ch);
this.YPixels = new byte[width * height]; this.YPixels = CleanPooler<byte>.RentCleanArray(width * height);
this.CbPixels = new byte[cw * ch]; this.CbPixels = CleanPooler<byte>.RentCleanArray(cw * ch);
this.CrPixels = new byte[cw * ch]; this.CrPixels = CleanPooler<byte>.RentCleanArray(cw * ch);
this.Ratio = ratio; this.Ratio = ratio;
this.YOffset = yOffset;
this.COffset = cOffset;
this.YStride = width; this.YStride = width;
this.CStride = cw; this.CStride = cw;
this.X = 0; this.X = 0;
@ -41,8 +44,10 @@ namespace ImageSharp.Formats.Jpg
/// <summary> /// <summary>
/// Prevents a default instance of the <see cref="YCbCrImage"/> class from being created. /// Prevents a default instance of the <see cref="YCbCrImage"/> class from being created.
/// </summary> /// </summary>
private YCbCrImage() private YCbCrImage(int yOffset, int cOffset)
{ {
this.YOffset = yOffset;
this.COffset = cOffset;
} }
/// <summary> /// <summary>
@ -84,38 +89,38 @@ namespace ImageSharp.Formats.Jpg
/// <summary> /// <summary>
/// Gets or sets the luminance components channel. /// Gets or sets the luminance components channel.
/// </summary> /// </summary>
public byte[] YPixels { get; private set; } public byte[] YPixels { get; }
/// <summary> /// <summary>
/// Gets or sets the blue chroma components channel. /// Gets or sets the blue chroma components channel.
/// </summary> /// </summary>
public byte[] CbPixels { get; private set; } public byte[] CbPixels { get; }
/// <summary> /// <summary>
/// Gets or sets the red chroma components channel. /// Gets or sets the red chroma components channel.
/// </summary> /// </summary>
public byte[] CrPixels { get; private set; } public byte[] CrPixels { get; }
/// <summary> /// <summary>
/// Gets or sets the Y slice index delta between vertically adjacent pixels. /// Gets or sets the Y slice index delta between vertically adjacent pixels.
/// </summary> /// </summary>
public int YStride { get; private set; } public int YStride { get; }
/// <summary> /// <summary>
/// Gets or sets the red and blue chroma slice index delta between vertically adjacent pixels /// Gets or sets the red and blue chroma slice index delta between vertically adjacent pixels
/// that map to separate chroma samples. /// that map to separate chroma samples.
/// </summary> /// </summary>
public int CStride { get; private set; } public int CStride { get; }
/// <summary> /// <summary>
/// Gets or sets the index of the first luminance element. /// Gets or sets the index of the first luminance element.
/// </summary> /// </summary>
public int YOffset { get; private set; } public int YOffset { get; }
/// <summary> /// <summary>
/// Gets or sets the index of the first element of red or blue chroma. /// Gets or sets the index of the first element of red or blue chroma.
/// </summary> /// </summary>
public int COffset { get; private set; } public int COffset { get; }
/// <summary> /// <summary>
/// Gets or sets the horizontal position. /// Gets or sets the horizontal position.
@ -132,32 +137,6 @@ namespace ImageSharp.Formats.Jpg
/// </summary> /// </summary>
public YCbCrSubsampleRatio Ratio { get; set; } public YCbCrSubsampleRatio Ratio { get; set; }
///// <summary>
///// Gets an image made up of a subset of the originals pixels.
///// </summary>
///// <param name="x">The x-coordinate of the image.</param>
///// <param name="y">The y-coordinate of the image.</param>
///// <param name="width">The width.</param>
///// <param name="height">The height.</param>
///// <returns>
///// The <see cref="YCbCrImage"/>.
///// </returns>
//public YCbCrImage Subimage(int x, int y, int width, int height)
//{
// YCbCrImage ret = new YCbCrImage
// {
// YPixels = this.YPixels,
// CbPixels = this.CbPixels,
// CrPixels = this.CrPixels,
// Ratio = this.Ratio,
// YStride = this.YStride,
// CStride = this.CStride,
// YOffset = (y * this.YStride) + x,
// COffset = (y * this.CStride) + x
// };
// return ret;
//}
/// <summary> /// <summary>
/// Returns the offset of the first luminance component at the given row /// Returns the offset of the first luminance component at the given row
/// </summary> /// </summary>
@ -236,5 +215,12 @@ namespace ImageSharp.Formats.Jpg
break; break;
} }
} }
public void Dispose()
{
CleanPooler<byte>.ReturnArray(this.YPixels);
CleanPooler<byte>.ReturnArray(this.CrPixels);
CleanPooler<byte>.ReturnArray(this.CbPixels);
}
} }
} }

10
src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs

@ -472,6 +472,7 @@ namespace ImageSharp.Formats
this.huffmanTrees[i].Dispose(); this.huffmanTrees[i].Dispose();
} }
this.ycbcrImage?.Dispose();
this.bytes.Dispose(); this.bytes.Dispose();
this.grayImage.ReturnPooled(); this.grayImage.ReturnPooled();
this.blackImage.ReturnPooled(); this.blackImage.ReturnPooled();
@ -2059,8 +2060,8 @@ namespace ImageSharp.Formats
if (this.componentCount == 1) if (this.componentCount == 1)
{ {
JpegPixelArea gray = JpegPixelArea.CreatePooled(8 * mxx, 8 * myy); this.grayImage = JpegPixelArea.CreatePooled(8 * mxx, 8 * myy);
this.grayImage = gray.Subimage(0, 0, this.imageWidth, this.imageHeight); //this.grayImage = gray.Subimage(0, 0, this.imageWidth, this.imageHeight);
} }
else else
{ {
@ -2092,9 +2093,8 @@ namespace ImageSharp.Formats
break; break;
} }
this.ycbcrImage = new YCbCrImage(8 * h0 * mxx, 8 * v0 * myy, ratio); this.ycbcrImage = new YCbCrImage(8 * h0 * mxx, 8 * v0 * myy, ratio, 0, 0);
//this.ycbcrImage = ycbcr.Subimage(0, 0, this.imageWidth, this.imageHeight);
if (this.componentCount == 4) if (this.componentCount == 4)
{ {
int h3 = this.componentArray[3].HorizontalFactor; int h3 = this.componentArray[3].HorizontalFactor;

2
src/ImageSharp/Formats/Jpg/Utils/ArrayPoolManager.cs → src/ImageSharp/Formats/Jpg/Utils/CleanPooler.cs

@ -2,7 +2,7 @@
{ {
using System.Buffers; using System.Buffers;
internal class ArrayPoolManager<T> internal class CleanPooler<T>
{ {
private static readonly ArrayPool<T> Pool = ArrayPool<T>.Create(); private static readonly ArrayPool<T> Pool = ArrayPool<T>.Create();
Loading…
Cancel
Save