Use array pools in editing images.

This commit is contained in:
atravita-mods 2022-08-15 19:13:39 -04:00 committed by Jesse Plamondon-Willard
parent 7c90385d8d
commit 78643710ce
No known key found for this signature in database
GPG Key ID: CF8B1456B3E29F49
1 changed files with 28 additions and 15 deletions

View File

@ -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 // 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 />
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);