Use array pools in editing images.
This commit is contained in:
parent
7c90385d8d
commit
78643710ce
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
@ -47,44 +48,55 @@ namespace StardewModdingAPI.Framework.Content
|
||||||
int areaHeight = sourceArea.Value.Height;
|
int areaHeight = sourceArea.Value.Height;
|
||||||
|
|
||||||
if (areaX == 0 && areaY == 0 && areaWidth == source.Width && areaHeight == source.Height)
|
if (areaX == 0 && areaY == 0 && areaWidth == source.Width && areaHeight == source.Height)
|
||||||
|
{
|
||||||
sourceData = source.Data;
|
sourceData = source.Data;
|
||||||
|
this.PatchImageImpl(sourceData, source.Width, source.Height, sourceArea.Value, targetArea.Value, patchMode);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sourceData = new Color[areaWidth * areaHeight];
|
int pixelCount = areaWidth * areaHeight;
|
||||||
int i = 0;
|
sourceData = ArrayPool<Color>.Shared.Rent(pixelCount);
|
||||||
for (int y = areaY, maxY = areaY + areaHeight - 1; y <= maxY; y++)
|
|
||||||
|
for (int y = areaY, maxY = areaY + areaHeight; y < maxY; y++)
|
||||||
{
|
{
|
||||||
for (int x = areaX, maxX = areaX + areaWidth - 1; x <= maxX; x++)
|
// avoiding an variable that increments allows the processor to re-arrange here.
|
||||||
{
|
int sourceIndex = (y * source.Width) + areaX;
|
||||||
int targetIndex = (y * source.Width) + x;
|
int targetIndex = (y - areaY) * areaWidth;
|
||||||
sourceData[i++] = source.Data[targetIndex];
|
Array.Copy(source.Data, sourceIndex, sourceData, targetIndex, areaWidth);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// apply
|
||||||
|
this.PatchImageImpl(sourceData, source.Width, source.Height, sourceArea.Value, targetArea.Value, patchMode);
|
||||||
|
|
||||||
|
// return
|
||||||
|
ArrayPool<Color>.Shared.Return(sourceData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply
|
|
||||||
this.PatchImageImpl(sourceData, source.Width, source.Height, sourceArea.Value, targetArea.Value, patchMode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void PatchImage(Texture2D source, Rectangle? sourceArea = null, Rectangle? targetArea = null, PatchMode patchMode = PatchMode.Replace)
|
public void PatchImage(Texture2D source, Rectangle? sourceArea = null, Rectangle? targetArea = null, PatchMode patchMode = PatchMode.Replace)
|
||||||
{
|
{
|
||||||
|
// validate
|
||||||
|
if (source == null)
|
||||||
|
throw new ArgumentNullException(nameof(source), "Can't patch from a null source texture.");
|
||||||
|
|
||||||
this.GetPatchBounds(ref sourceArea, ref targetArea, source.Width, source.Height);
|
this.GetPatchBounds(ref sourceArea, ref targetArea, source.Width, source.Height);
|
||||||
|
|
||||||
// validate source texture
|
// validate source texture
|
||||||
if (source == null)
|
|
||||||
throw new ArgumentNullException(nameof(source), "Can't patch from a null source texture.");
|
|
||||||
if (!source.Bounds.Contains(sourceArea.Value))
|
if (!source.Bounds.Contains(sourceArea.Value))
|
||||||
throw new ArgumentOutOfRangeException(nameof(sourceArea), "The source area is outside the bounds of the source texture.");
|
throw new ArgumentOutOfRangeException(nameof(sourceArea), "The source area is outside the bounds of the source texture.");
|
||||||
|
|
||||||
// get source data
|
// get source data
|
||||||
int pixelCount = sourceArea.Value.Width * sourceArea.Value.Height;
|
int pixelCount = sourceArea.Value.Width * sourceArea.Value.Height;
|
||||||
Color[] sourceData = GC.AllocateUninitializedArray<Color>(pixelCount);
|
Color[] sourceData = ArrayPool<Color>.Shared.Rent(pixelCount);
|
||||||
source.GetData(0, sourceArea, sourceData, 0, pixelCount);
|
source.GetData(0, sourceArea, sourceData, 0, pixelCount);
|
||||||
|
|
||||||
// apply
|
// apply
|
||||||
this.PatchImageImpl(sourceData, source.Width, source.Height, sourceArea.Value, targetArea.Value, patchMode);
|
this.PatchImageImpl(sourceData, source.Width, source.Height, sourceArea.Value, targetArea.Value, patchMode);
|
||||||
|
|
||||||
|
// return
|
||||||
|
ArrayPool<Color>.Shared.Return(sourceData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
@ -143,7 +155,7 @@ namespace StardewModdingAPI.Framework.Content
|
||||||
if (patchMode == PatchMode.Overlay)
|
if (patchMode == PatchMode.Overlay)
|
||||||
{
|
{
|
||||||
// get target data
|
// get target data
|
||||||
Color[] mergedData = GC.AllocateUninitializedArray<Color>(pixelCount);
|
Color[] mergedData = ArrayPool<Color>.Shared.Rent(pixelCount);
|
||||||
target.GetData(0, targetArea, mergedData, 0, pixelCount);
|
target.GetData(0, targetArea, mergedData, 0, pixelCount);
|
||||||
|
|
||||||
// merge pixels
|
// merge pixels
|
||||||
|
@ -175,6 +187,7 @@ namespace StardewModdingAPI.Framework.Content
|
||||||
}
|
}
|
||||||
|
|
||||||
target.SetData(0, targetArea, mergedData, 0, pixelCount);
|
target.SetData(0, targetArea, mergedData, 0, pixelCount);
|
||||||
|
ArrayPool<Color>.Shared.Return(mergedData);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
target.SetData(0, targetArea, sourceData, 0, pixelCount);
|
target.SetData(0, targetArea, sourceData, 0, pixelCount);
|
||||||
|
|
Loading…
Reference in New Issue