Texture2D rotation really expensive on Android

My main problem is that when I load pictures from my Android Device they are fliped (while they aren’t in my device) but I don’t know how to fix this. So I’m trying to rotate the image when I try to visualize on Unity.

So I have this method to rotate texture 90º clockwise and counterclockwise. The problem is that with large images, like the ones that I’m working on, which are pictures taken by an Android Device that creates 4-5MB per picture, results on a REALLY slow process (takes more than 2 seconds to complete the rotation).

I’m doing something wrong? It’s normal cause the size of the images? There’s another approach? Many thanks!

//Grab Texture and return the same texture rotated 90 degrees clockwise
public static Texture2D RotateTexture90(Texture originalTexture, bool clockwise, bool affectOriginalResource = false)
{
    Texture2D source = (Texture2D)originalTexture;
    Color32[] colorSource = source.GetPixels32();
    Color32[] colorResult = new Color32[colorSource.Length];

    int count = 0;
    int newWidth = source.height;
    int newHeight = source.width;
    int index = 0;

    for (int i = 0; i < source.width; i++)
    {
        for (int j = 0; j < source.height; j++)
        {
            if (clockwise)
                index = (source.width * (j + 1)) - (i + 1);
            else
                index = (source.width * (source.height - j)) - source.width + i;

            colorResult[count] = colorSource[index];
            count++;
        }
    }

    if(affectOriginalResource)
    {
        source.Resize(newWidth, newHeight);
        source.SetPixels32(colorResult);
        source.Apply();
        Debug.Log("Finish Rotation");
        return source;
    }
    else
    {
        Texture2D rotatedTexture = new Texture2D(newWidth, newHeight);
        rotatedTexture.SetPixels32(colorResult);
        rotatedTexture.Apply();
        Debug.Log("Finish Rotation");
        return rotatedTexture;
    }
}

That’s expected to take so long, though I am wondering why the image is flipped in the first place

In any case, such operations like rotating/flipping should be done via shaders, you should tweak texture uv coordinates, but certainly not pixels itself

Re “when I try to visualize on Unity” - you can do something like this to have things working differently based on whether code is running in the editor vs. on the device:

#if UNITY_EDITOR
  if (Application.isPlaying)
  {
    // runs in Editor during Play Mode
  } else {
    // runs in Editor during Edit Mode
  }
#else
  #if UNITY_ANDROID
    // runs on Android platform build
  #else
    // runs on non-Android builds
  #endif
#endif

Edit: fixed commenting

I’m wondering the same, maybe you can help me @Tomas1856 ? I’m capturing images with this code, it’s my own Android Plugin:

private void dispatchTakePictureIntent() {
    PackageManager packageManager = getActivity().getPackageManager();
    if(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY))
    {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION );

        // Ensure that there's a camera activity to handle the intent
        if (takePictureIntent.resolveActivity(packageManager) != null) {
            // Create the File where the photo should go
            File photoFile = null;
            try {
                photoFile = createImageFile();
            } catch (IOException ex) {
                Log.d(TAG, "Error occurred while creating the File:"+ex.toString());
            }
            // Continue only if the File was successfully created
            if (photoFile != null) {
                Uri photoURI = FileProvider.getUriForFile(getActivity(),
                        "com.eric.nativetoolkit.fileprovider",
                        photoFile);
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
                startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
            }
        }
    }
}

The method that creates the file is this one:

private File createImageFile() throws IOException
{
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPG_" + timeStamp + "_";
    File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);

    File image = File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",  /* suffix */
            storageDir      /* directory */
    );

    currentPhotoPath = image.getAbsolutePath();
    return image;
}

I’m only sending the path of the image (currentPhotoPath) like “/storage/emulated/0/Pictures/JPG_20200820_113850_1984505146372720601.jpg”.
And loaded into Texture2D like this:

public static Texture2D LoadPNG(string filePath)
    {

        Texture2D tex = null;
        byte[] fileData;

        if (File.Exists(filePath))
        {
            fileData = File.ReadAllBytes(filePath);
            tex = new Texture2D(Screen.width, Screen.height);
            tex.LoadImage(fileData); //..this will auto-resize the texture dimensions.
        }
        else
        {
            Debug.Log("FilePath " + filePath + "do not exist");
        }
        return tex;
    }

Then I simply assign this Texture2D to a RawImage.texture.

Thanks for your help @Tomas1856 , and meanwhile I’ll check how to do this UV flip with shaders. (if you think that this question should be another new post tell me and I will move it)

Thanks for your answer @adamgolden but I don’t get how checking the platform I’m working on could help me with the rotation issues :S

I mentioned that because you said “I’m trying to rotate the image when I try to visualize on Unity.” Maybe you could make it easier to visualize/work with until this is resolved? If it’s running in the editor do this, if it’s on a device do that.

Are you in portrait mode?

I’ve tested portrait, landscape, forcing each one, letting auto-rotation, every loaded picture is fliped 90º:(

You are trying to rotate on the cpu, better use shader for that job, and assign the webcamtexture to material