Serialize Image

The whole answer can be found below.

Please note: The Photon forum is closed permanently. After many dedicated years of service we have made the decision to retire our forum and switch to read-only: we've saved the best to last! And we offer you support through these channels:

Try Our
Documentation

Please check if you can find an answer in our extensive documentation on PUN.

Join Us
on Discord

Meet and talk to our staff and the entire Photon-Community via Discord.

Read More on
Stack Overflow

Find more information on Stack Overflow (for Circle members only).

Write Us
an E-Mail

Feel free to send your question directly to our developers.

Serialize Image

StyleMaster
2017-06-21 11:49:38

I want to spawn a RawImage over the network.
I've added this script to a prefab to be spawned:

[RequireComponent(typeof(PhotonView))]  
public class exchange_frame : MonoBehaviour {

    [SerializeField]  
    public RawImage rawImage;

    void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)  
    {  
        if (stream.isWriting)  
        {  
            stream.SendNext(rawImage);  
        }  
        else  
        {  
            rawImage = (RawImage)stream.ReceiveNext();  
        }  
    }  
}

But I received the following:

Exception: cannot serialize(): UnityEngine.UI.RawImage

Should I convert to byte[] ? Or what else?

Comments

[Deleted User]
2017-06-22 08:27:10

Hi @StyleMaster,

you can either convert the RawImage to a byte array (byte arrays are supported by PUN out of the box) or register a custom type to directly use this type in OnPhotonSerializeView. You can read about Custom Types on this guide and follow the example which shows how Vector2 is supported by PUN.

Is this RawImage changed a lot so that it requires you to use OnPhotonSerializeView? If you just want to send this like once each ten minutes, you might want to take a look at RaiseEvent function and use this for sending because OnPhotonSerializeView is called 20 times a second (default settings) which would result in a lot of used bandwidth and messages.

StyleMaster
2017-06-22 08:36:15

Unfortunatly yes.
My application has this scenario:

  • Master client spawn the texture over the network.
  • Non-master client get frames from camera and show them on a texture.
    Right now I´ve developed the following code. The texture appears on both but the master client seems to don´t receive the updated texture....

Master client code:
public class exchange_frame : MonoBehaviour {
public RawImage rawImage;
private Texture2D tex;
[SerializeField]
private byte[] rawData;
void Update()
{
if (rawData.Length > 0)
{
tex.LoadImage(rawData);
rawImage.material.mainTexture = tex;
rawImage.texture = tex;
}
}

void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)  
{  
    if (stream.isWriting)  
    { }  
    else  
    {  
        rawData = (byte[])stream.ReceiveNext();  
    }  
}  

}

Non-Master client code:
public RawImage rawImage;
private Texture2D tex;
private GameObject backgroundCam;
private RawImage streamCam;
[SerializeField]
private byte[] rawData;
void Start()
{
backgroundCam = GameObject.FindGameObjectWithTag("cameraBackground");
streamCam = (RawImage)backgroundCam.GetComponent();
}

void Update()  
{  
    rawImage = streamCam;  
    Texture2D tex = (Texture2D) streamCam.texture;  
    rawData = tex.EncodeToPNG();  
}

void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)  
{  
    if (stream.isWriting)  
    {  
        stream.SendNext(rawData);  
    }  
    else  
    {  
    }  
}

StyleMaster
2017-06-22 08:38:05

The application is getting really slow since I´ve added this code, so I think that is really sending data in some way over the network but for some reasons are not received on the master client

StyleMaster
2017-06-22 08:43:41

Master client (spawn the object and receive bytes):

[RequireComponent(typeof(PhotonView))]  
public class exchange_frame : MonoBehaviour {  
    public RawImage rawImage;  
    private Texture2D tex;
[SerializeField]  
private byte[] rawData;  
void Update()  
{  
    if (rawData.Length > 0)  
    {  
        tex.LoadImage(rawData);  
        rawImage.material.mainTexture = tex;  
        rawImage.texture = tex;  
    }  
}

void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)  
{  
    if (stream.isWriting)  
    {  
    }  
    else  
    {  
        rawData = (byte[])stream.ReceiveNext();  
          
    }  
}  

}

Non Master client (send bytes):
[RequireComponent(typeof(PhotonView))]  
public class exchange_frame : MonoBehaviour {   
    public RawImage rawImage;  
    private Texture2D tex;  
    private GameObject backgroundCam;  
    private RawImage streamCam;
[SerializeField]  
private byte[] rawData;  
void Start()  
{  
    backgroundCam = GameObject.FindGameObjectWithTag("cameraBackground");  
    streamCam = (RawImage)backgroundCam.GetComponent<RawImage>();  
      
}  
void Update()  
{  
    rawImage = streamCam;  
    Texture2D tex = (Texture2D) streamCam.texture;  
    rawData = tex.EncodeToPNG();  
}

void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)  
{  
    if (stream.isWriting)  
    {  
        stream.SendNext(rawData);  
    }  
    else  
    {  
    }  
}  

}

[Deleted User]
2017-06-22 08:48:01

You don't need two separate scripts for this. You need to network instantiate an object which has an attached PhotonView component which furthermore observes an attached scripts with OnPhotonSerializeView function where you have both cases: stream.isWriting and stream.isReading. Also the RawImage component needs to be attached to this game object.

StyleMaster
2017-06-22 08:56:24

So the Non-Master client should only load the prefab from resources and change texture? (without send it in OnPhotonSerializeView)?

[Deleted User]
2017-06-22 09:03:10

Whoever should send the data needs to network instantiate this game object (PhotonNetwork.Instantiate(...) function). This way the object gets instantiated on each other client as well, but only the owner writes data to the stream, everyone else is just reading from the stream. In your case only the non-MasterClient(s) should instantiate these objects. However this only works for two clients and need to be extended for more than two clients, if you want to support that.

StyleMaster
2017-06-22 09:28:46

Tried right now: "Client is not the MasterClient in this room" .. it can´t instantiate gameobject if it is not the masterclient

[Deleted User]
2017-06-22 12:51:36

Do you use PhotonNetwork.Instantiate or PhotonNetwork.InstantiateSceneObject? The second one can only be called by the MasterClient.

StyleMaster
2017-06-28 16:14:59

I changed to Instantiate.
Now I have some problems converting the Texture2D into byte[].
This part:

Texture2D tex = (Texture2D) streamCam.texture;
rawData = tex.EncodeToPNG();

Give me an "invalid cast" error.
If I change to :

tex = rawImage.texture as Texture2D;

I have no errors but the texture is empty, so nothing to show .

I have to precise that the Texture I´m sending comes from a webcam.
Any suggestions?

Back to top