Search code examples
c#opencvunity-game-enginetexture2dopenvr

Convert Texture2D to Byte[] using EncodeToJPG (in OpenVR)


I have one question!

I just want, just...convert Texture2D to Byte[] using EncodeToJPG() function!

My workspace is Unity and C# Script, + OpenCvSharp.

Maybe you think that It is easy, but It have some problem.

this script use OpenVR(HTC VIVE).

Anyway, Here is my source.

var source = SteamVR_TrackedCamera.Source(undistorted);

//Receive texture data from VR.
texture = source.texture;

//Debug.Log(source.texture.width + "/" + source.texture.height);    
//size : 612 /460
if (texture == null)
{
    return;
}

//Input texture data into material, and it's in unity (quad GameObject).
//this G.O print display like camera
material.mainTexture = texture;


//here is my src, I want to save Image but texture.EncodeToJPG has some error.
Cv2.ImShow("_Texture ...", Mat.FromImageData(texture.EncodeToJPG()));
Cv2.ImWrite(SavePath+ "Image.jpg", Mat.FromImageData(texture.EncodeToJPG()));

and...there is problem. variable texture is abnormal Texture2D type.

if (_texture == null)
{
    _texture = Texture2D.CreateExternalTexture((int)header.nWidth, (int)header.nHeight, TextureFormat.RGBA32, false, false, nativeTex);
    //_texture = new Texture2D(612, 460, TextureFormat.RGBA32, false);

    uint width = 0, height = 0;
    var frameBounds = new VRTextureBounds_t();
    if (trackedCamera.GetVideoStreamTextureSize(deviceIndex, frameType, ref frameBounds, ref width, ref height) == EVRTrackedCameraError.None)
    {
        // Account for textures being upside-down in Unity.
        frameBounds.vMin = 1.0f - frameBounds.vMin;
        frameBounds.vMax = 1.0f - frameBounds.vMax;
        this.frameBounds = frameBounds;
    }
}
else
{
    _texture.UpdateExternalTexture(nativeTex);
    //_texture.Apply();
}

that _texture is created by function CreateExternalTexture and it has parameter of Intptr type named nativeTex.

I don't know how can I do?

+++ edit! Error display +++

enter image description here


Solution

  • declared this function:

    private Texture2D ReadExternalTexture(Texture externalTexture)
    {
        Texture2D myTexture2D = new Texture2D(texture.width, texture.height);
        //myTexture2D => empty Texture2D type variable
        if (myTexture2D == null)
        {
            Debug.Log("var: myTexture2D is null state.");
            myTexture2D = new Texture2D(texture.width, texture.height);
        }
    
        //Make RenderTexture type variable
        RenderTexture tmp = RenderTexture.GetTemporary(
        externalTexture.width,
        externalTexture.height,
        0,
        RenderTextureFormat.ARGB32,
        RenderTextureReadWrite.sRGB);
    
        Graphics.Blit(externalTexture, tmp);
        RenderTexture previous = RenderTexture.active;
        RenderTexture.active = tmp;
    
        myTexture2D.ReadPixels(new UnityEngine.Rect(0, 0, tmp.width, tmp.height), 0,     0);
        myTexture2D.Apply();
    
        RenderTexture.active = previous;
        RenderTexture.ReleaseTemporary(tmp);
    
        return myTexture2D;
    }
    

    and use ReadExternalTexture Function in void Update():

    _texture = ReadExternalTexture(material.mainTexture);
    
    Mat mat = Mat.FromImageData(_texture.EncodeToPNG());
    
    Cv2.Flip(mat, mat, 0);
    //Flip(src, dest, 0->updown flip / 1->leftright flip)
    
    Cv2.Resize(mat, mat, new Size(224, 224));
    
    Cv2.ImShow("Image", mat);
    //Cv2.ImWrite(SavePath + "Image.jpg", mat);
    

    and this worked totally!