diff --git a/Plugins/TextureOps/TextureOps.cs b/Plugins/TextureOps/TextureOps.cs index 2541f38..7a4f9dc 100644 --- a/Plugins/TextureOps/TextureOps.cs +++ b/Plugins/TextureOps/TextureOps.cs @@ -247,6 +247,54 @@ public static bool SaveImage( byte[] sourceBytes, string imagePath ) #endregion #region Texture Operations + public static Texture2D Crop( Texture sourceTex, int leftOffset, int topOffset, int width, int height, TextureFormat format = TextureFormat.RGBA32, Options options = new Options() ) + { + if( sourceTex == null ) + throw new ArgumentException( "Parameter 'sourceTex' is null!" ); + + if( width <= 0 || width > sourceTex.width ) + width = sourceTex.width; + if( height <= 0 || height > sourceTex.height ) + height = sourceTex.height; + if( leftOffset <= 0 ) + leftOffset = 0; + else if( leftOffset + width > sourceTex.width ) + leftOffset = sourceTex.width - width; + if( topOffset <= 0 ) + topOffset = 0; + else if( topOffset + height > sourceTex.height ) + topOffset = sourceTex.height - height; + + Texture2D result = null; + + RenderTexture rt = RenderTexture.GetTemporary( sourceTex.width, sourceTex.height ); + RenderTexture activeRT = RenderTexture.active; + + try + { + Graphics.Blit( sourceTex, rt ); + RenderTexture.active = rt; + + result = new Texture2D( width, height, format, options.generateMipmaps, options.linearColorSpace ); + result.ReadPixels( new Rect( leftOffset, sourceTex.height - topOffset - height, width, height ), 0, 0, false ); + result.Apply( options.generateMipmaps, options.markNonReadable ); + } + catch( Exception e ) + { + Debug.LogException( e ); + + Object.Destroy( result ); + result = null; + } + finally + { + RenderTexture.active = activeRT; + RenderTexture.ReleaseTemporary( rt ); + } + + return result; + } + public static Texture2D Scale( Texture sourceTex, int targetWidth, int targetHeight, TextureFormat format = TextureFormat.RGBA32, Options options = new Options() ) { if( sourceTex == null ) @@ -329,7 +377,7 @@ public static bool SaveImage( byte[] sourceBytes, string imagePath ) return result; } - + public static Texture2D[] Slice( Texture sourceTex, int sliceTexWidth, int sliceTexHeight, TextureFormat format = TextureFormat.RGBA32, Options options = new Options() ) { if( sourceTex == null ) @@ -394,41 +442,6 @@ public static bool SaveImage( byte[] sourceBytes, string imagePath ) return result; } - - public static Texture2D Crop(Texture sourceTex, int x, int y, int width, int height, TextureFormat format = TextureFormat.RGBA32, Options options = new Options()) - { - if( sourceTex == null ) - throw new ArgumentException( "Parameter 'sourceTex' is null!" ); - - Texture2D result = null; - - RenderTexture rt = RenderTexture.GetTemporary( sourceTex.width, sourceTex.height ); - RenderTexture activeRT = RenderTexture.active; - - try - { - Graphics.Blit( sourceTex, rt ); - RenderTexture.active = rt; - - result = new Texture2D( width, height, format, options.generateMipmaps, options.linearColorSpace ); - result.ReadPixels( new Rect( x, sourceTex.height - y - height, width, height ), 0, 0, false ); - result.Apply( options.generateMipmaps, options.markNonReadable ); - } - catch( Exception e ) - { - Debug.LogException( e ); - - Object.Destroy( result ); - result = null; - } - finally - { - RenderTexture.active = activeRT; - RenderTexture.ReleaseTemporary( rt ); - } - - return result; - } #endregion #region Helper Functions diff --git a/README.md b/README.md index deba516..4e09aba 100644 --- a/README.md +++ b/README.md @@ -42,14 +42,14 @@ Simply import [TextureOps.unitypackage](https://github.com/yasirkula/UnityTextur **NOTE:** on some Android devices, these functions may not work correctly when called with a *sourceTex* that was created in the same frame. Therefore, if you'd like to call these functions immediately after *LoadImage*, consider instead waiting for at least one frame. You can use `yield return null;` in a coroutine to wait for one frame. +`Texture2D[] TextureOps.Crop( Texture2D, sourceTex, int leftOffset, int topOffset, int width, int height, TextureFormat format = TextureFormat.RGBA32, TextureOps.Options options )`: crops sourceTex and returns the cropped texture. + `Texture2D TextureOps.Scale( Texture2D sourceTex, int targetWidth, int targetHeight, TextureFormat format = TextureFormat.RGBA32, TextureOps.Options options )`: scales *sourceTex* to the specified size and returns the scaled texture. sourceTex's aspect ratio may not be preserved. `Texture2D TextureOps.ScaleFill( Texture2D sourceTex, int targetWidth, int targetHeight, Color32 fillColor, TextureFormat format = TextureFormat.RGBA32, TextureOps.Options options )`: scales *sourceTex* to the specified size and returns the scaled texture. sourceTex's aspect ratio is preserved and blank space is filled with *fillColor*. `Texture2D[] TextureOps.Slice( Texture2D sourceTex, int sliceTexWidth, int sliceTexHeight, TextureFormat format = TextureFormat.RGBA32, TextureOps.Options options )`: slices *sourceTex* into smaller textures and returns these textures in an array. sourceTex is sliced row-by-row, starting from top-left corner. Note that if a 100-pixel-wide texture is sliced into 30-pixel-wide textures, rightmost 10 pixels will be discarded. Likewise, if a 100-pixel-wide texture is sliced into 101-pixel-wide textures, the returned array will be empty. -`Texture2D[] TextureOps.Crop( Texture2D, sourceTex, int x, int y, int width, int height, TextureFormat format = TextureFormat.RGBA32, TextureOps.Options options )`: cuts a rectangle out of the source texture into a new texture. - ### C. Utility Functions `TextureOps.ImageProperties TextureOps.GetImageProperties( string imagePath )`: *[Android & iOS only]* returns an *ImageProperties* instance that holds the width, height, mime type and EXIF orientation information of an image file without creating a *Texture2D* object. Mime type will be *null*, if it can't be determined.