1+ using System . Collections . Generic ;
2+ using UnityEngine ;
3+ using System . Threading . Tasks ;
4+
5+ namespace Gameframe . Procgen
6+ {
7+ // Only works on ARGB32, RGB24 and Alpha8 textures that are marked readable
8+ public static class TextureScale
9+ {
10+ public class TaskData
11+ {
12+ public int start ;
13+ public int end ;
14+
15+ public TaskData ( int s , int e )
16+ {
17+ start = s ;
18+ end = e ;
19+ }
20+ }
21+
22+ public static async Task PointAsync ( Texture2D tex , int newWidth , int newHeight )
23+ {
24+ await ThreadedScaleAsync ( tex , newWidth , newHeight , false ) ;
25+ }
26+
27+ public static async Task BilinearAsync ( Texture2D tex , int newWidth , int newHeight )
28+ {
29+ await ThreadedScaleAsync ( tex , newWidth , newHeight , true ) ;
30+ }
31+
32+ private static async Task ThreadedScaleAsync ( Texture2D tex , int newWidth , int newHeight , bool useBilinear )
33+ {
34+ var texColors = tex . GetPixels ( ) ;
35+ var newColors = new Color [ newWidth * newHeight ] ;
36+
37+ float ratioX ;
38+ float ratioY ;
39+ if ( useBilinear )
40+ {
41+ ratioX = 1.0f / ( ( float ) newWidth / ( tex . width - 1 ) ) ;
42+ ratioY = 1.0f / ( ( float ) newHeight / ( tex . height - 1 ) ) ;
43+ }
44+ else
45+ {
46+ ratioX = ( ( float ) tex . width ) / newWidth ;
47+ ratioY = ( ( float ) tex . height ) / newHeight ;
48+ }
49+
50+ var width = tex . width ;
51+
52+ var cores = Mathf . Min ( SystemInfo . processorCount , newHeight ) ;
53+ var slice = newHeight / cores ;
54+
55+ var tasks = new List < Task > ( ) ;
56+
57+ if ( cores > 1 )
58+ {
59+ for ( var i = 0 ; i < cores ; i ++ )
60+ {
61+ var taskData = new TaskData ( slice * i , slice * ( i + 1 ) ) ;
62+ var task = Task . Run ( ( ) =>
63+ {
64+ if ( useBilinear )
65+ {
66+ BilinearScale ( taskData , texColors , newColors , width , newWidth , ratioX , ratioY ) ;
67+ }
68+ else
69+ {
70+ PointScale ( taskData , texColors , newColors , width , newWidth , ratioX , ratioY ) ;
71+ }
72+ } ) ;
73+ tasks . Add ( task ) ;
74+ }
75+ await Task . WhenAll ( tasks ) ;
76+ }
77+ else
78+ {
79+ var taskData = new TaskData ( 0 , newHeight ) ;
80+ await Task . Run ( ( ) =>
81+ {
82+ if ( useBilinear )
83+ {
84+ BilinearScale ( taskData , texColors , newColors , width , newWidth , ratioX , ratioY ) ;
85+ }
86+ else
87+ {
88+ PointScale ( taskData , texColors , newColors , width , newWidth , ratioX , ratioY ) ;
89+ }
90+ } ) ;
91+ }
92+
93+ tex . Resize ( newWidth , newHeight ) ;
94+ tex . SetPixels ( newColors ) ;
95+ tex . Apply ( ) ;
96+ }
97+
98+ private static void BilinearScale ( TaskData taskData , Color [ ] texColors , Color [ ] newColors , int width , int newWidth , float ratioX , float ratioY )
99+ {
100+ for ( var y = taskData . start ; y < taskData . end ; y ++ )
101+ {
102+ int yFloor = ( int ) Mathf . Floor ( y * ratioY ) ;
103+ var y1 = yFloor * width ;
104+ var y2 = ( yFloor + 1 ) * width ;
105+ var yw = y * newWidth ;
106+
107+ for ( var x = 0 ; x < newWidth ; x ++ )
108+ {
109+ int xFloor = ( int ) Mathf . Floor ( x * ratioX ) ;
110+ var xLerp = x * ratioX - xFloor ;
111+ newColors [ yw + x ] = ColorLerpUnclamped (
112+ ColorLerpUnclamped ( texColors [ y1 + xFloor ] , texColors [ y1 + xFloor + 1 ] , xLerp ) ,
113+ ColorLerpUnclamped ( texColors [ y2 + xFloor ] , texColors [ y2 + xFloor + 1 ] , xLerp ) ,
114+ y * ratioY - yFloor ) ;
115+ }
116+ }
117+ }
118+
119+ private static void PointScale ( TaskData taskData , Color [ ] texColors , Color [ ] newColors , int width , int newWidth , float ratioX , float ratioY )
120+ {
121+ for ( var y = taskData . start ; y < taskData . end ; y ++ )
122+ {
123+ var thisY = ( int ) ( ratioY * y ) * width ;
124+ var yw = y * newWidth ;
125+ for ( var x = 0 ; x < newWidth ; x ++ )
126+ {
127+ newColors [ yw + x ] = texColors [ ( int ) ( thisY + ratioX * x ) ] ;
128+ }
129+ }
130+ }
131+
132+ private static Color ColorLerpUnclamped ( Color c1 , Color c2 , float value )
133+ {
134+ return new Color ( c1 . r + ( c2 . r - c1 . r ) * value ,
135+ c1 . g + ( c2 . g - c1 . g ) * value ,
136+ c1 . b + ( c2 . b - c1 . b ) * value ,
137+ c1 . a + ( c2 . a - c1 . a ) * value ) ;
138+ }
139+
140+ }
141+ }
0 commit comments