Search Unity

  1. New Unity Live Help updates. Check them out here!

    Dismiss Notice

Assets [RELEASED] Image Cropper - multiplatform image cropping solution with oval mask support

Discussion in 'Works In Progress' started by yasirkula, Apr 15, 2018.

  1. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    1,367


    Hi there,

    Image Cropper aims to be a powerful, customizable and easy-to-use image cropping solution for Unity. It is created with Unity's UI system.

    Features
    - Supports rectangular and oval cropping modes
    - Supports auto-zoom feature for fine-tuning the selection
    - Costs 1 SetPass call and 6 batches (assuming that Sprite Packing is enabled in Editor Settings)
    - Can work on pretty much any screen resolution/orientation

    Asset Store: https://assetstore.unity.com/packages/tools/gui/image-cropper-116650
    Also available at: https://github.com/yasirkula/UnityImageCropper
    WebGL demo: http://yasirkula.net/ImageCropperDemo/

    Enjoy!
     
    Last edited: Mar 3, 2020
    FayyadSufyan likes this.
  2. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    1,367
  3. FayyadSufyan

    FayyadSufyan

    Joined:
    Feb 25, 2016
    Posts:
    28
    I'm interested (if not expensive) as it will save me some time.
     
  4. Pode

    Pode

    Joined:
    Nov 13, 2013
    Posts:
    117
    Thanks for the product, and thanks for the various assets you provided on the store before !
     
    yasirkula likes this.
  5. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    1,367
    Much appreciated, thanks.
     
  6. huynh_do

    huynh_do

    Joined:
    Jan 11, 2018
    Posts:
    1
    thank you so much
     
  7. brownce

    brownce

    Joined:
    Sep 14, 2015
    Posts:
    15
    I know you mentioned not really being able to provide support for this asset, but I'm running into a small issue that is having it crash on iOS.

    Occasionally when trying to select an image, it suddenly crashes.

    xcode logs are showing the message "Creatig an image format with an unknown type is an error", however I do seem to also get this message and not have it crash. Currently though the crash happens during the image picking process. Using Unity 2018.3 if that helps.

    Any idea what might be going on? I'm currently trying to find any info online, but I'm not familiar with native code stuff. Any assistance or direction you might be able to provide would be greatly appreciated.

    Thanks!
     
    Last edited: Feb 25, 2019
  8. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    1,367
    How are you picking the image? Do you use NativeGallery, perhaps?
     
  9. brownce

    brownce

    Joined:
    Sep 14, 2015
    Posts:
    15
    Yes, we are using your NativeGallery plugin as well.
     
  10. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    1,367
    Does this crash occur after getting a number of images from Photos, or does it occur the first time? If it is the former, then probably undestroyed textures quickly fill all the free memory and the game crashes. In this case, destroying unused procedural textures manually via Destroy function and/or settings a lower minSize while using LoadImageAtPath might help resolve this issue.
     
  11. brownce

    brownce

    Joined:
    Sep 14, 2015
    Posts:
    15
    It's actually fairly random. I have had it happen when selecting an image or sometimes when I hit the crop button. I thought it was a memory issue also, but it isn't consistent on the number of images.

    I have had it do several images without fail before suddenly it crashes and then other times I do a couple and it crashes.

    We have a feature that lets the user choose an image for the profile picture. Then the cropper allows them to crop out the part for the profile. It always crashes somewhere during that process.

    Also to note it only is crashing on iOS during this process, I couldn't get it to crash on Android at all no matter how much I tried to mess it up.

    I tried really hard on Android because I tend to find logcat a great debugging tool.
     
  12. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    1,367
    Please make sure that it is not related to memory using Xcode's memory profiler (Memory Use). Also try setting a very low minSize value (like 32, for testing purposes) to see if it changes anything. If it is not a memory issue, then I have no ideas, unfortunately.
     
  13. isplayer

    isplayer

    Joined:
    Dec 6, 2016
    Posts:
    1
    [EDIT]
    I solved the problem, the error was happening because my texture wasnt readeble, so i cannot modify, after changing it to readable the plugin worked perfectly.



    Hi, i'm having trouble to call a function if my crop is succed, the plugin stop, the crop screen don't disappear and the lines after my function call doesn't run, the problem occurs on "SetUserPhoto(croppedImage)" call, here is my code:

    Code (CSharp):
    1. IEnumerator CropImage(Texture2D tex)
    2.     {
    3.         yield return new WaitForEndOfFrame();
    4.  
    5.         bool ovalSelection = false;
    6.         bool autoZoom = false;
    7.  
    8.         ImageCropper.Instance.Show(tex, (bool result, Texture originalImage, Texture2D croppedImage) =>
    9.         {
    10.             // Destroy previously cropped texture (if any) to free memory
    11.             //Destroy(fotoUsuario.texture, 5f);
    12.  
    13.             // If screenshot was cropped successfully
    14.             if (result)
    15.             {
    16.                 SetUserPhoto(croppedImage);
    17.                 // Assign cropped texture to the RawImage
    18.                 FotoUser.enabled = true;
    19.                 FotoUser.texture = croppedImage;
    20.  
    21.                 Vector2 size = FotoUser.rectTransform.sizeDelta;
    22.                 if (croppedImage.height <= croppedImage.width)
    23.                     size = new Vector2(500f, 500f * (croppedImage.height / (float)croppedImage.width));
    24.                 else
    25.                     size = new Vector2(500f * (croppedImage.width / (float)croppedImage.height), 500f);
    26.                 FotoUser.rectTransform.sizeDelta = size;
    27.             }
    28.             else
    29.             {
    30.                 //fotoUsuario.enabled = false;
    31.             }
    32.  
    33.             // Destroy the screenshot as we no longer need it in this case
    34.             Destroy(tex);
    35.         },
    36.         settings: new ImageCropper.Settings()
    37.         {
    38.             ovalSelection = ovalSelection,
    39.             autoZoomEnabled = autoZoom,
    40.             imageBackground = Color.clear, // transparent background
    41.             visibleButtons = ImageCropper.Button.None,
    42.             selectionMinSize = new Vector2(400, 400)
    43.  
    44.         },
    45.         croppedImageResizePolicy: (ref int width, ref int height) =>
    46.         {
    47.             width = 400;
    48.             height = 400;
    49.         });
    50.     }
    And here is my SetUserPhoto function:

    Code (CSharp):
    1. public void SetUserPhoto(Texture2D tex)
    2.     {
    3.         byte[] bytes = tex.EncodeToPNG();
    4.         if (File.Exists(Path.Combine(Application.persistentDataPath, "FotoUsuario.jpg")))
    5.             File.Delete(Path.Combine(Application.persistentDataPath, "FotoUsuario.jpg"));
    6.         File.WriteAllBytes(Path.Combine(Application.persistentDataPath, "FotoUsuario.jpg"), bytes);
    7.  
    8.         StartCoroutine(UploadJPG());
    9.     }
     
    Last edited: Jul 9, 2019
    yasirkula likes this.
  14. pankti12

    pankti12

    Joined:
    Oct 28, 2017
    Posts:
    5
    Hello,

    Can I want to crop the image of size 540 width and 960 height, how can I achieve it?
    I tried setting the min and max ratio to 9 and16.
     
  15. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    1,367
    You can set selectionMinSize and selectionMaxSize to new Vector2(540,960). Alternatively, you can set selectionMinAspectRatio and selectionMaxAspectRatio to 540f/960f and register to the croppedImageResizePolicy:

    Code (CSharp):
    1. croppedImageResizePolicy: ( ref int width, ref int height ) =>
    2. {
    3.     width = 540;
    4.     height = 960;
    5. } );
     
  16. pankti12

    pankti12

    Joined:
    Oct 28, 2017
    Posts:
    5
    Thanks, but I also do not want crop guidelines to change its size from 540x960. So, I used
    Thanks :)
     
  17. pariwo

    pariwo

    Joined:
    Dec 13, 2019
    Posts:
    2
    Hello
    I wanna save cropped image in some folder, but IDK the method.
    Would you tell me how to do that?
     
  18. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    1,367
    ImageCropper.Instance.Show takes a Settings parameter which has a markTextureNonReadable property, first you should set is as false. Then, you can use the following code to save the cropped Texture to persistentDataPath:

    Code (CSharp):
    1. string filePath = System.IO.Path.Combine( Application.persistentDataPath, "Image.png" );
    2. System.IO.File.WriteAllBytes( filePath, texture.EncodeToPNG() );
     
  19. pariwo

    pariwo

    Joined:
    Dec 13, 2019
    Posts:
    2
    Thank you so mach !

     
  20. fajriardiansyahh

    fajriardiansyahh

    Joined:
    Apr 10, 2019
    Posts:
    5
    Hello sir, I had issue using your crop. By the way I'm using your native.gallery to get an image. The issue that I found is, after I selected any image(single image) it's goes back to the main scene without nothing. The "ImageCropper" prefab didn't show up. Kindly advise what should I do?
     
  21. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    1,367
    May I see your code? Are there any error messages in logcat/Xcode console/log file?
     
  22. fajriardiansyahh

    fajriardiansyahh

    Joined:
    Apr 10, 2019
    Posts:
    5
    Hello again Sir,
    I've tried around twentieth times re-compile my app. Trying to solve above situation. But I never come up with a good results. Some are crash some are not showing the prefab and some are the crop button won't clicked. Below is the latest code that I tried
    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4.  
    5. namespace ImageCropperNamespace
    6. {
    7.     public class ImageCropperDemo : MonoBehaviour
    8.     {
    9.         public RawImage croppedImageHolder;
    10.         public Text croppedImageSize;
    11.  
    12.         public Toggle ovalSelectionInput, autoZoomInput;
    13.         public InputField minAspectRatioInput, maxAspectRatioInput;
    14.  
    15.         public Image Image1;
    16.  
    17.         public void PickImage1(int maxSize)
    18.         {
    19.             NativeGallery.Permission check = NativeGallery.CheckPermission();
    20.             string result = check.ToString();
    21.             if (result == "ShouldAsk" || result == "Denied")
    22.             {
    23.                 NativeGallery.Permission request = NativeGallery.RequestPermission();
    24.             }
    25.             else
    26.             {
    27.                 NativeGallery.Permission permissionGranted = NativeGallery.GetImageFromGallery((path) =>
    28.                 {
    29.  
    30.                     Debug.Log("Image path: " + path);
    31.                     if (path != null)
    32.                     {
    33.                         // Create Texture from selected image
    34.                         Texture2D myTexture = NativeGallery.LoadImageAtPath(path, maxSize);
    35.                         if (myTexture == null)
    36.                         {
    37.                             Debug.Log("Couldn't load texture from " + path);
    38.                             return;
    39.                         }
    40.                         else
    41.                         {
    42.                             Cropping(myTexture);
    43.                         }
    44.                     }
    45.                 }, "Select a PNG image", "image/png");
    46.  
    47.                 Debug.Log("Permission result: " + permissionGranted);
    48.             }
    49.         }
    50.  
    51.         private void Cropping(Texture2D myTexture)
    52.         {
    53.             bool autoZoom = true;
    54.  
    55.             ImageCropper.Instance.Show(myTexture, (bool result, Texture originalImage, Texture2D croppedImage) => {
    56.  
    57.                 if (result)
    58.                 {
    59.                     Image1.sprite = Sprite.Create(croppedImage, new Rect(0, 0, myTexture.width, myTexture.height), new Vector2(0, 0));
    60.                 }
    61.             },
    62.             settings: new ImageCropper.Settings()
    63.             {
    64.                 autoZoomEnabled = autoZoom,
    65.                 imageBackground = Color.clear // transparent background
    66.                
    67.  
    68.             },
    69.             croppedImageResizePolicy: (ref int width, ref int height) =>
    70.             {
    71.                 // uncomment lines below to save cropped image at half resolution
    72.                 //width /= 2;
    73.                 //height /= 2;
    74.             });
    75.         }
    : The Result is: Crop Button cannot work but the cancel and the other it works.
     
  23. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    1,367
    Making the following change in your code fixed the issue for me:
    Image1.sprite = Sprite.Create( croppedImage, new Rect( 0, 0, croppedImage.width, croppedImage.height ), new Vector2( 0, 0 ) );
    . Just make sure that you've assigned an Image object to Image1.
     
  24. fajriardiansyahh

    fajriardiansyahh

    Joined:
    Apr 10, 2019
    Posts:
    5
    Oh my goodd! It works, Thank you sir, what a dumb I miss that width and height. I think I'm a bit of tired. Thank you so much!! for the correction.
     
    yasirkula likes this.
  25. fajriardiansyahh

    fajriardiansyahh

    Joined:
    Apr 10, 2019
    Posts:
    5
    Hello again sir, I think I will ask one more question. How to set the cropping tool (the square) to be the size that I want of your "Image Cropper". So the user cannot resize the square, they will just move the the square into the location that he or she want to make a picture of their pict.
     
  26. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    1,367
    With something like this:

    Code (CSharp):
    1. settings: new ImageCropper.Settings()
    2. {
    3.     autoZoomEnabled = autoZoom,
    4.     imageBackground = Color.clear,
    5.     selectionMinSize = new Vector2(100,100),
    6.     selectionMaxSize = new Vector2(100,100)
    7. },
    You can find all available parameters in the documentation: https://github.com/yasirkula/UnityImageCropper#c-how-to
     
  27. fajriardiansyahh

    fajriardiansyahh

    Joined:
    Apr 10, 2019
    Posts:
    5
    Hello sir, thanks it is worked. Sorry for the late reply since I'm straight to do other tasks. Thank you so much. May I ask one more question?
     
  28. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    1,367
    Please ask the question straight away.
     
  29. RishiPrakaash

    RishiPrakaash

    Joined:
    Nov 12, 2019
    Posts:
    2
    hi sir, i am getting image load from user and after some filter i am trying to save it back to gallery. so i need fixed size cropping at fixed place(like at top of the panel (image height =300 and width = 250 of panel height =600 and width =277) without displaying cropping selection graphic
     
    Last edited: Mar 5, 2020
  30. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    1,367
    You can use this function:

    Code (CSharp):
    1. public Texture2D CropImage( Texture2D source, int width, int height, int xOffset, int yOffset )
    2. {
    3.     if( width <= 0 || width > source.width )
    4.         width = source.width;
    5.     if( height <= 0 || height > source.height )
    6.         height = source.height;
    7.  
    8.     if( xOffset <= 0 )
    9.         xOffset = 0;
    10.     else if( xOffset + width > source.width )
    11.         xOffset = source.width - width;
    12.  
    13.     if( yOffset <= 0 )
    14.         yOffset = 0;
    15.     else if( yOffset + height > source.height )
    16.         yOffset = source.height - height;
    17.  
    18.     Texture2D result = new Texture2D( width, height, source.format, source.mipmapCount > 0 );
    19.     result.SetPixels( source.GetPixels( xOffset, yOffset, width, height ) );
    20.     result.Apply();
    21.  
    22.     return result;
    23. }
    In your case, call it like this:

    Code (CSharp):
    1. int cropWidth = 250;
    2. int cropHeight = 300;
    3. Texture2D newTexture = CropImage( originalTexture, cropWidth, cropHeight, ( originalTexture.width - cropWidth ) / 2, originalTexture.height - cropHeight );
     
    RishiPrakaash likes this.
  31. RishiPrakaash

    RishiPrakaash

    Joined:
    Nov 12, 2019
    Posts:
    2
    thank you @yasirkula it worked, sorry for the late reply
     
    yasirkula likes this.
  32. josemachado_dev

    josemachado_dev

    Joined:
    Mar 16, 2018
    Posts:
    5
    Hi there!

    We are using this plugin on an a mobile application.
    Everything was working correctly, both on Android and on iOS, but when we upgraded some devices to Android 10 this plugin has stop working as intended on those devices only, but with the same build it still works on Androids 9 or older.

    Are there any more reports of this happening?
     
  33. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    1,367
    What happens when testing the plugin on Android 10? And are there any error messages in logcat?
     
  34. josemachado_dev

    josemachado_dev

    Joined:
    Mar 16, 2018
    Posts:
    5
    We've granted access permission to access the device's Photos and Images, but still it returns an error saying that it doesn't have permission to access the image at the given image path (although the path was defined by searching it through the device's explorer), returning a null image.
    Again, this behavior is not replicated in Android 9 or below.
    upload_2020-3-25_18-40-48.png
     
  35. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    1,367
    Image Cropper has no functions to load textures from files, so this is not related to Image Cropper. It is probably a Storage Access Framework issue and you can try using this plugin to pick images with a file browser, it supports Storage Access Framework.
     
  36. josemachado_dev

    josemachado_dev

    Joined:
    Mar 16, 2018
    Posts:
    5
    After some more digging, you are correct. The issue does not seem to be happening with this plugin, but with the Native Gallery plugin. I'll move over to that thread, with more detail of the code that's giving errors now.
    Thank you for your help!
     
unityunity