Skip to content

Commit

Permalink
Added KKAPI.Utilities.TextureUtils.ResizeTexture extension
Browse files Browse the repository at this point in the history
  • Loading branch information
ManlyMarco committed May 27, 2021
1 parent 545a450 commit 83e9bf6
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 0 deletions.
1 change: 1 addition & 0 deletions doc/KKAPI.Utilities.md
Expand Up @@ -288,6 +288,7 @@ Static Methods
| Type | Name | Summary |
| --- | --- | --- |
| `Texture2D` | LoadTexture(this `Byte[]` texBytes, `TextureFormat` format = ARGB32, `Boolean` mipMaps = False) | Create texture from an image stored in a byte array, for example a png file read from disk. |
| `Texture2D` | ResizeTexture(this `Texture2D` pSource, `ImageFilterMode` pFilterMode, `Single` pScale) | Create a resized copy of this texture. http://blog.collectivemass.com/2014/03/resizing-textures-in-unity/ |
| `Sprite` | ToSprite(this `Texture2D` texture) | Create a sprite based on this texture. |
| `Texture2D` | ToTexture2D(this `Texture` tex, `TextureFormat` format = ARGB32, `Boolean` mipMaps = False) | Copy this texture inside a new editable Texture2D. |

Expand Down
139 changes: 139 additions & 0 deletions src/Shared.Core/Utilities/TextureUtils.cs
Expand Up @@ -53,5 +53,144 @@ public static Sprite ToSprite(this Texture2D texture)
if (texture == null) throw new ArgumentNullException(nameof(texture));
return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
}

/// <summary>
/// Filtering to use when resizing a texture
/// </summary>
public enum ImageFilterMode
{
/// <summary>
/// Nearest pixel, fastest but gets aliased
/// </summary>
Nearest = 0,
/// <summary>
/// Use bilinear scaling
/// </summary>
Biliner = 1,
/// <summary>
/// Average of all nearby pixels
/// </summary>
Average = 2
}

/// <summary>
/// Create a resized copy of this texture.
/// http://blog.collectivemass.com/2014/03/resizing-textures-in-unity/
/// </summary>
/// <param name="pSource">Texture to resize</param>
/// <param name="pFilterMode">How to resize</param>
/// <param name="pScale">New scale</param>
public static Texture2D ResizeTexture(this Texture2D pSource, ImageFilterMode pFilterMode, float pScale)
{
//*** Variables
int i;

//*** Get All the source pixels
Color[] aSourceColor = pSource.GetPixels(0);
Vector2 vSourceSize = new Vector2(pSource.width, pSource.height);

//*** Calculate New Size
float xWidth = Mathf.RoundToInt((float)pSource.width * pScale);
float xHeight = Mathf.RoundToInt((float)pSource.height * pScale);

//*** Make New
Texture2D oNewTex = new Texture2D((int)xWidth, (int)xHeight, TextureFormat.RGBA32, false);

//*** Make destination array
int xLength = (int)xWidth * (int)xHeight;
Color[] aColor = new Color[xLength];

Vector2 vPixelSize = new Vector2(vSourceSize.x / xWidth, vSourceSize.y / xHeight);

//*** Loop through destination pixels and process
Vector2 vCenter = new Vector2();
for (i = 0; i < xLength; i++)
{

//*** Figure out x&y
float xX = (float)i % xWidth;
float xY = Mathf.Floor((float)i / xWidth);

//*** Calculate Center
vCenter.x = (xX / xWidth) * vSourceSize.x;
vCenter.y = (xY / xHeight) * vSourceSize.y;

//*** Do Based on mode
//*** Nearest neighbour (testing)
if (pFilterMode == ImageFilterMode.Nearest)
{

//*** Nearest neighbour (testing)
vCenter.x = Mathf.Round(vCenter.x);
vCenter.y = Mathf.Round(vCenter.y);

//*** Calculate source index
int xSourceIndex = (int)((vCenter.y * vSourceSize.x) + vCenter.x);

//*** Copy Pixel
aColor[i] = aSourceColor[xSourceIndex];
}

//*** Bilinear
else if (pFilterMode == ImageFilterMode.Biliner)
{

//*** Get Ratios
float xRatioX = vCenter.x - Mathf.Floor(vCenter.x);
float xRatioY = vCenter.y - Mathf.Floor(vCenter.y);

//*** Get Pixel index's
int xIndexTL = (int)((Mathf.Floor(vCenter.y) * vSourceSize.x) + Mathf.Floor(vCenter.x));
int xIndexTR = (int)((Mathf.Floor(vCenter.y) * vSourceSize.x) + Mathf.Ceil(vCenter.x));
int xIndexBL = (int)((Mathf.Ceil(vCenter.y) * vSourceSize.x) + Mathf.Floor(vCenter.x));
int xIndexBR = (int)((Mathf.Ceil(vCenter.y) * vSourceSize.x) + Mathf.Ceil(vCenter.x));

//*** Calculate Color
aColor[i] = Color.Lerp(
Color.Lerp(aSourceColor[xIndexTL], aSourceColor[xIndexTR], xRatioX),
Color.Lerp(aSourceColor[xIndexBL], aSourceColor[xIndexBR], xRatioX),
xRatioY
);
}

//*** Average
else if (pFilterMode == ImageFilterMode.Average)
{

//*** Calculate grid around point
int xXFrom = (int)Mathf.Max(Mathf.Floor(vCenter.x - (vPixelSize.x * 0.5f)), 0);
int xXTo = (int)Mathf.Min(Mathf.Ceil(vCenter.x + (vPixelSize.x * 0.5f)), vSourceSize.x);
int xYFrom = (int)Mathf.Max(Mathf.Floor(vCenter.y - (vPixelSize.y * 0.5f)), 0);
int xYTo = (int)Mathf.Min(Mathf.Ceil(vCenter.y + (vPixelSize.y * 0.5f)), vSourceSize.y);

//*** Loop and accumulate
Vector4 oColorTotal = new Vector4();
Color oColorTemp = new Color();
float xGridCount = 0;
for (int iy = xYFrom; iy < xYTo; iy++)
{
for (int ix = xXFrom; ix < xXTo; ix++)
{

//*** Get Color
oColorTemp += aSourceColor[(int)(((float)iy * vSourceSize.x) + ix)];

//*** Sum
xGridCount++;
}
}

//*** Average Color
aColor[i] = oColorTemp / (float)xGridCount;
}
}

//*** Set Pixels
oNewTex.SetPixels(aColor);
oNewTex.Apply();

//*** Return
return oNewTex;
}
}
}

0 comments on commit 83e9bf6

Please sign in to comment.