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
  4. Dismiss Notice

Fast conversion from Texture2D to UIImage

Discussion in 'iOS and tvOS' started by fcloss, Mar 14, 2013.

  1. fcloss

    fcloss

    Joined:
    Dec 1, 2011
    Posts:
    191
    Hi all,

    I've create a library to record videos from unity sequence of images (tex). Basically to allow my app to export its content to videos.

    It works, but very slowly. Mainly because to convert the Texture2D (from the RenderTexture) to the UIImage, then to add to the video frame, I encode the texture in PNG, get the bytes and call the native objective-C, which creates the UIImage. The action of encoding to makes this task really slow. Here is the code in both sides:

    Unity:

    Code (csharp):
    1. byte[] bytes = m_TexSshot.EncodeToPNG();
    2. AVWriterUnity.appendFrameFromImage(bytes,(uint)bytes.Length,a_TimeInMs);
    Code (csharp):
    1. public static void appendFrameFromImage(byte[] a_ImageBuffer,uint a_BufferLength, long a_FrameTimeInMilliseconds)
    2. {
    3.         if (Application.platform == RuntimePlatform.IPhonePlayer)
    4.             _appendFrameFromImage(a_ImageBuffer,a_BufferLength,a_FrameTimeInMilliseconds);
    5.    
    6. }
    7.  
    XCode:

    Code (csharp):
    1. bool _appendFrameFromImage(const void* a_ImageBuffer,unsigned int a_BufferLength, int64_t a_FrameTimeInMilliseconds)
    2. {
    3.    
    4.     //Create UIIMage from buffer
    5.     NSData* imageData = [[NSData alloc] initWithBytes:a_ImageBuffer length:a_BufferLength];
    6.     UIImage* image = [[UIImage alloc] initWithData:imageData];
    7. ...

    Anyone have any idea of a simples as fast way to send the byte array to obj-c in such a way that it understands to create the UIImage, but without having to encode it to PNG?

    Thanks very much.

    Regards,
    Fernando
     
  2. ryo0ka

    ryo0ka

    Joined:
    Sep 27, 2015
    Posts:
    37
    Fernando, have you found a solution to this by chance?

    Best,
    Ryo
     
  3. Yum1994

    Yum1994

    Joined:
    Jul 19, 2016
    Posts:
    4
    The funny thing is, after 10 years later, I am facing the same problem as you guys. :) Can anyone provide the correct way to pass png encoded byte[] to the Objective-c side and convert it to UIImage?

    Much Appreciated!
     
  4. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,602
  5. Yum1994

    Yum1994

    Joined:
    Jul 19, 2016
    Posts:
    4
    Finally! The problem is the "length" argument isn't passing correctly. In your code, you should change from:
    Code (CSharp):
    1. AVWriterUnity.appendFrameFromImage(bytes, (uint) bytes.Length, a_TimeInMs);
    to:
    Code (CSharp):
    1. // There is no need to cast to "uint", "int" will be fine
    2. AVWriterUnity.appendFrameFromImage(bytes, (bytes.Length * sizeof(byte)), a_TimeInMs);
    And the funtion signature should be:
    Code (CSharp):
    1. // Passing pointer
    2. public static void appendFrameFromImage(byte* a_ImageBuffer, int a_BufferLength, long a_FrameTimeInMilliseconds)
    3. // The calling side in C# should be
    4. byte[] bytes = m_TexSshot.EncodeToPNG();
    5. fixed (byte* ptrBytes = bytes )
    6. {
    7. AVWriterUnity.appendFrameFromImage(ptrBytes, (bytes.Length * sizeof(byte)), a_TimeInMs);
    8. }
    For Objective-c side you should write the function as
    Code (CSharp):
    1. bool _appendFrameFromImage(const Byte* a_ImageBuffer, int a_BufferLength, int64_t a_FrameTimeInMilliseconds)
     
    Last edited: Sep 5, 2023