Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

WebCamTexture flipping and rotating 90 degree (IOS and android)

Discussion in 'Editor & General Support' started by bniranjan, Jul 16, 2012.

  1. bniranjan

    bniranjan

    Joined:
    Jul 16, 2012
    Posts:
    1
    I tried to use WebCamTexture to show the output of the hardware camera on the screen. i used following code to initialize and play web camera.

    Code:-

    WebCamTexture mycam=new WebCamTexture();
    mycam.play();

    And onGui() i passed the mycam to GUI.DrawTexture.


    This works fine on the unity player (which uses the web camera on the PC), but doesnt work properly on Android/iOS Devices. The images on the devices are flipped and rotated 90 degrees.

    Please help us on this so that we can make it similar like what it shows in Unity Player.
     
    makaka-org likes this.
  2. davidf

    davidf

    Joined:
    Oct 12, 2012
    Posts:
    4
    I am having the same problem, but I am trying to put the texture onto a game object.
     
  3. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,602
  4. slumtrimpet

    slumtrimpet

    Joined:
    Mar 18, 2014
    Posts:
    372
    Not sure if it's user error on my part or if this has just changed sometime in the last 3ish years... but when projecting my webcamTexture onto a RawImage from the "new" UI (Unity > 4.6), it appears the rotation axis is different than the docs show. Using 'Vector3.up' for me made my RawImage rotate on the Y axis and disappear from the UI canvas all together.

    I had to change:
    Code (csharp):
    1. transform.rotation = baseRotation * Quaternion.AngleAxis(webcamTexture.videoRotationAngle, Vector3.up);
    To:
    Code (csharp):
    1. transform.rotation = baseRotation * Quaternion.AngleAxis(webcamTexture.videoRotationAngle, Vector3.back);
     
    mdrunk and BrennanZ like this.
  5. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,602
    hm, most likely thats because new UI use "special" "for-UI" coordinate system. Can you please bug report with small repro (so i wont loose it) - we will check and or update docs or fix the thing
     
  6. slumtrimpet

    slumtrimpet

    Joined:
    Mar 18, 2014
    Posts:
    372
    Submitted a bug. Not exactly sure how best to link it here, but it's case: 708628.
    Thanks
     
  7. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,602
    i tried it on what-would-soon-become-5.2, and it works like a charm, so most likely some UI something
    small remark - you have
    #elif UNITY_IOS
    previewRect.localScale=new Vector3(1,-1,1);
    #endif

    this is not cool, you should use http://docs.unity3d.com/ScriptReference/WebCamTexture-videoVerticallyMirrored.html
    if i force it to pick back-facing camera image will be shown mirrored.

    so i would say your workaround is good enough for now, just keep in mind that on upgrading you might have it fixed automagically ;-)
     
  8. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,602
    ok, upon closer looking (all hail our awesome QA) it seems there is smth fishy in there - it depends on screen orientation. I will recheck what's up (as in - is it error on our end or you actually missed smth)
     
  9. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,602
    After some poking of UI people:
    That is really UI coming into play. So essentially you use screen space Canvas (not world space), so whatever you put into it - is expected to be in XY plane, so if you want to apply video rotation angle you should rotate around Z axis (which is back/front).
    Now if we speak about our docs sample - it uses normal 3d rendering and kinda "expect" to be drawn on plane so if you want to apply video rotation you need to rotate around Y (up), as initially plane is in XZ (you can check it in editor).
    I hope that clarifies, so your workaround is actually "let user fix user errors" ;-). But i agree we need to update docs
     
  10. slumtrimpet

    slumtrimpet

    Joined:
    Mar 18, 2014
    Posts:
    372
    Awesome Alexey, thanks for your time looking into that. Glad I'm not way off base either. :)
     
  11. Notter

    Notter

    Joined:
    Mar 8, 2015
    Posts:
    65
    Hello, I'm having the same issue, when trying to show the WebCamTexture on RawImage.

    webcamTexture.videoRotationAngle always returns the value "180", when i'm testing it with "Unity Remote 4".
    So i'm not sure how can i know if i need to rotate my camera texture to know when the view is flipped (landscape left/right)
     
  12. nOsmircK

    nOsmircK

    Joined:
    Mar 18, 2014
    Posts:
    8
    I have the same issue, I'm trying to place a WebCamTexture to a RawImage and the image is rotated 90 degrees to the left.

    I'm initializing the texture in Awake and I set the Start Method as a IEnumerator, waiting 2 seconds before I actually set the texture to the RawImage. I wait 1 second, then Play() the WebCamTexture, after another second, I Stop and set everything. This way I can correctly get the width and height of the texture and the VideoRotationAngle (which is 90 in my case).

    Now, I set up the aspect ratio of the image using AspetcRatioFitter. The problem is that it is rotated 90 degrees.

    Rotating the GameObject works fine (although it doesn't fit in the screen as it should and it can be fixed with some more code by scaling it to fit the screen) but before I get into that, I'd like to know if there is a way to change the UV coordinates for the RawImage Mesh, this way, I can freely rotate those coordinates around the center the amount of degrees the WebCamTexture is reporting and forget about the scale.
     
  13. KazYamof

    KazYamof

    Joined:
    Jun 26, 2015
    Posts:
    59
    How to serialize the texture with the correct orientation after fixing the rotation issue??? I mean, rotate the game object transform to 'fix' on UI is simple, but the Texture2D is still 90 deg rotated.
     
  14. slumtrimpet

    slumtrimpet

    Joined:
    Mar 18, 2014
    Posts:
    372
    Been a long time since I poked at this (and maybe what I did here was dumb)... but it ends up being a hack where you manually translate the thing:

    Code (csharp):
    1.  
    2.   private Texture2D rotate90(Texture2D orig) {
    3.     print("doing rotate90");
    4.     Color32[] origpix = orig.GetPixels32(0);
    5.     Color32[] newpix = new Color32[orig.width * orig.height];
    6.     for(int c = 0; c < orig.height; c++) {
    7.       for(int r = 0; r < orig.width; r++) {
    8.         newpix[orig.width * orig.height - (orig.height * r + orig.height) + c] =
    9.           origpix[orig.width * orig.height - (orig.width * c + orig.width) + r];
    10.       }
    11.     }
    12.     Texture2D newtex = new Texture2D(orig.height, orig.width, orig.format, false);
    13.     newtex.SetPixels32(newpix, 0);
    14.     newtex.Apply();
    15.     return newtex;
    16.   }
    17.  
    18.   private Texture2D rotate180(Texture2D orig) {
    19.     print("doing rotate180");
    20.     Color32[] origpix = orig.GetPixels32(0);
    21.     Color32[] newpix = new Color32[orig.width * orig.height];
    22.     for(int i = 0; i < origpix.Length; i++) {
    23.       newpix[origpix.Length - i - 1] = origpix[i];
    24.     }
    25.     Texture2D newtex = new Texture2D(orig.width, orig.height, orig.format, false);
    26.     newtex.SetPixels32(newpix, 0);
    27.     newtex.Apply();
    28.     return newtex;
    29.   }
    30.  
    31.   private Texture2D rotate270(Texture2D orig) {
    32.     print("doing rotate270");
    33.     Color32[] origpix = orig.GetPixels32(0);
    34.     Color32[] newpix = new Color32[orig.width * orig.height];
    35.     int i = 0;
    36.     for(int c = 0; c < orig.height; c++) {
    37.       for(int r = 0; r < orig.width; r++) {
    38.         newpix[orig.width * orig.height - (orig.height * r + orig.height) + c] = origpix[i];
    39.         i++;
    40.       }
    41.     }
    42.     Texture2D newtex = new Texture2D(orig.height, orig.width, orig.format, false);
    43.     newtex.SetPixels32(newpix, 0);
    44.     newtex.Apply();
    45.     return newtex;
    46.   }
    47.  
     
    fjc, wdr434-domowe, ROBYER1 and 3 others like this.
  15. RuslanIrokez

    RuslanIrokez

    Joined:
    Jul 18, 2018
    Posts:
    1
  16. funnykakak

    funnykakak

    Joined:
    Oct 10, 2019
    Posts:
    1
  17. pavelsvs2012

    pavelsvs2012

    Joined:
    Oct 6, 2020
    Posts:
    8
    This summer there was a need to redraw the texture in the same way. Faced with the problem of heavy textures. Many mobile devices take photos in 4k format (iphone for example) and it takes 5-10 seconds to rotate such a texture. It's a very long time. It works faster on a PC, but it's a PC.
    In general, I personally came to the conclusion that I rotated the object itself during the execution of the program, after which I sent it to the server for saving (where I just redrawn it using the server API) and at the next interaction, the image returned already in the right angle.
     
  18. HasithaCJ

    HasithaCJ

    Joined:
    May 20, 2017
    Posts:
    11
    I had the same issue when tried to get camera input for RawTexture in android potrait mode. So I dcided to move on with a quad.

    I just modified this code to work on orthograhic camera. c# - How to get Live feed from phone camera to Unity - Stack Overflow

    Hope this will help you.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class CameraInputManager : MonoBehaviour
    4. {
    5.  
    6.     private WebCamTexture camTexture;
    7.     [SerializeField] private GameObject BackgroundQuad;
    8.     private Quaternion baseRotation;
    9.        
    10.     void Start()
    11.     {
    12.      
    13.        WebCamDevice[] devices = WebCamTexture.devices;
    14.        
    15.        if (devices.Length ==0)
    16.        {
    17.            Debug.Log("No camera");
    18.          
    19.            return;
    20.        }
    21.              
    22.        for (int i = 0; i < devices.Length; i++)
    23.        {        
    24.            if (devices[i].isFrontFacing) {
    25.              
    26.                camTexture = new WebCamTexture(devices[i].name,  Screen.height, Screen.width );
    27.              
    28.             }
    29.        }
    30.    
    31.  
    32.        if (camTexture == null) {
    33.            Debug.Log("Unable to find cam");
    34.          
    35.            return;
    36.        }
    37.  
    38.        baseRotation = transform.rotation;
    39.  
    40.        BackgroundQuad.GetComponent<Renderer>().material.mainTexture = camTexture;
    41.  
    42.        camTexture.Play();      
    43.              
    44.        CalculateBackgroundQuad();
    45.     }
    46.     void CalculateBackgroundQuad() {
    47.         Camera cam = Camera.main;
    48.         float ScreenRatio = (float)Screen.width / (float)Screen.height;
    49.  
    50.         float videoRotationAngle = camTexture.videoRotationAngle;
    51.  
    52.         BackgroundQuad.transform.localRotation = baseRotation * Quaternion.AngleAxis(camTexture.videoRotationAngle, Vector3.forward);
    53.      
    54.         float fixedHeight =  cam.orthographicSize*2;
    55.        
    56.         Vector3 QuadScale = new Vector3(1f, fixedHeight, 1f);
    57.         float TextureRatio;
    58.  
    59.         //adjust the scaling for portrait Mode & Landscape Mode
    60.         if (videoRotationAngle == 0 || videoRotationAngle == 180) {
    61.             //landscape mode
    62.             TextureRatio = (float)(camTexture.width) / (float)(camTexture.height);
    63.             if (ScreenRatio > TextureRatio) {
    64.                 float SH = ScreenRatio / TextureRatio;
    65.                 float TW = TextureRatio * fixedHeight * SH;
    66.                 float TH = fixedHeight * (camTexture.videoVerticallyMirrored ? -1 : 1) * SH;
    67.                 QuadScale = new Vector3(TW, TH, 1f);
    68.             } else {
    69.                 float TW = TextureRatio * fixedHeight;
    70.                 QuadScale = new Vector3(TW, fixedHeight * (camTexture.videoVerticallyMirrored ? -1 : 1), 1f);
    71.             }
    72.         } else {
    73.             //portrait mode
    74.             TextureRatio = (float)(camTexture.height) / (float)(camTexture.width);
    75.             if (ScreenRatio > TextureRatio) {
    76.                 float SH = ScreenRatio / TextureRatio;
    77.                 float TW = fixedHeight * -1f * SH;
    78.                 float TH = TW * (camTexture.videoVerticallyMirrored ? 1 : -1) * SH;
    79.                 QuadScale = new Vector3(TW, TH, 1f);
    80.             } else {
    81.                 float TW = TextureRatio * fixedHeight;
    82.                 QuadScale = new Vector3(fixedHeight * -1f, TW * (camTexture.videoVerticallyMirrored ? 1 : -1), 1f);
    83.             }
    84.         }
    85.         BackgroundQuad.transform.localScale = QuadScale;
    86.  
    87.     }
    88.  
    89. }
    90.  
     
  19. wdr434-domowe

    wdr434-domowe

    Joined:
    Jan 19, 2019
    Posts:
    1
    For me, rotating was not enough. I have to do flip vertical and horizontal. So if someone need it. Enjoy. I used @slumtrimpet code as inspiration.
    Code (CSharp):
    1.  
    2. private Texture2D FlipHorizontal(Texture2D orig)
    3. {
    4.     print("Doing FlipHorizontal");
    5.     Color32[] origpix = orig.GetPixels32(0);
    6.     Color32[] newpix = new Color32[orig.width * orig.height];
    7.  
    8.     for (int c = 0; c < orig.height; c++)
    9.     {
    10.         for(int i = 0; i < orig.width; i++)
    11.         {
    12.             newpix[(orig.width * (orig.height - 1 - c)) + i] = origpix[(c * orig.width) + i];
    13.         }
    14.     }
    15.  
    16.     Texture2D newtex = new Texture2D(orig.width, orig.height, orig.format, false);
    17.     newtex.SetPixels32(newpix, 0);
    18.     newtex.Apply();
    19.     return newtex;
    20. }
    21.  
    22. private Texture2D FlipVertical(Texture2D orig)
    23. {
    24.     print("Doing FlipVertical");
    25.     Color32[] origpix = orig.GetPixels32(0);
    26.     Color32[] newpix = new Color32[orig.width * orig.height];
    27.  
    28.     for (int c = 0; c < orig.height; c++)
    29.     {
    30.         for(int i = 0; i < orig.width; i++)
    31.         {
    32.             newpix[(c * orig.width) + (orig.width - 1 - i)] = origpix[(c * orig.width) + i];
    33.         }
    34.     }
    35.  
    36.     Texture2D newtex = new Texture2D(orig.width, orig.height, orig.format, false);
    37.     newtex.SetPixels32(newpix, 0);
    38.     newtex.Apply();
    39.     return newtex;
    40. }
    41.  
     
  20. makaka-org

    makaka-org

    Joined:
    Dec 1, 2013
    Posts:
    874
    Setting Rotation and Displaying for different cameras and platforms is not an easy task.

    I have next workaround using RawImage for displaying Camera Stream with WebCamTexture:
    Code (CSharp):
    1.  
    2.         Rect uvRectForVideoVerticallyMirrored = new(1f, 0f, -1f, 1f);
    3.         Rect uvRectForVideoNotVerticallyMirrored = new(0f, 0f, 1f, 1f);
    4.         Vector3 currentLocalEulerAngles = Vector3.zero;
    5. ----
    6. ----
    7. ----
    8.         if (webCamTexture && webCamTexture.width >= 100f)
    9.         {
    10.             currentCWNeeded = targetDevice.isFrontFacing
    11.                 ? webCamTexture.videoRotationAngle
    12.                 : -webCamTexture.videoRotationAngle;
    13.  
    14.             if (webCamTexture.videoVerticallyMirrored)
    15.             {
    16.                 currentCWNeeded += 180f;
    17.             }
    18.  
    19.             currentLocalEulerAngles.z = currentCWNeeded;
    20.             rawImage.rectTransform.localEulerAngles = currentLocalEulerAngles;
    21.  
    22.             if ((webCamTexture.videoVerticallyMirrored
    23.                 && !targetDevice.isFrontFacing)
    24.                 ||
    25.                 (!webCamTexture.videoVerticallyMirrored
    26.                 && targetDevice.isFrontFacing))
    27.             {
    28.                 rawImage.uvRect = uvRectForVideoVerticallyMirrored;
    29.             }
    30.             else
    31.             {
    32.                 rawImage.uvRect = uvRectForVideoNotVerticallyMirrored;
    33.             }
    34.         }
    35.  
    36.  
    P.S. I released Camera Feed on Background (docs) — Unity Asset which operates WebCamTexture class and does all the work for you.

    camera-feed-cover-made-with-unity.jpg