2016-08-08 46 views
0

Ich weiß, das wurde mehrmals gefragt ... und ich habe alles versucht und versucht, was ich kann, aber ich bin mir immer noch nicht sicher, warum ich die Ausnahme "Parameter ist nicht gültig" bekomme ...System.Drawing.Image Parameter nicht gültig

Ich habe eine Amazon EC2-Instanz, auf der Windows Server 2012 ausgeführt wird. Auf dieser Maschine verwende ich Unity3D (Unity 5). Diese Unity-Anwendung sendet Frames (Bilder) von der EC2-Instanz über TCP an meinen lokalen Laptop. Mein Client läuft mit Windows 10, nicht dass es einen Unterschied machen würde.

public void SendRaw(byte[] dataToSend) { 
    ///We must send the length of the message before sending the actual message 
    var sizeInfo = new byte[4]; // = BitConverter.GetBytes(dataToSend.Length); 

    //Shift the bytes 
    sizeInfo[0] = (byte) dataToSend.Length; 
    sizeInfo[1] = (byte)(dataToSend.Length >> 8); 
    sizeInfo[2] = (byte)(dataToSend.Length >> 16); 
    sizeInfo[3] = (byte)(dataToSend.Length >> 24); 

    try { 
    var stream = Client.GetStream(); 

    //Send the length of the data 
    stream.Write(sizeInfo, 0, 4); 
    //Send the data 
    stream.Write(dataToSend, 0, dataToSend.Length); 
    } catch (Exception ex) { 
    Debug.LogException(ex); 
    } finally { 
    //raise event to tell system that the client has disconnected and that listening must restart... 
    } 
} 
:

Um meine Bilddaten zu erhalten, ich folgendes:

byte[] GetScreenData() { 
    // Create a texture the size of the screen, RGB24 format 
    int width = Screen.width; 
    int height = Screen.height; 

    RenderTexture rt = new RenderTexture(width, height, 24); 

    Texture2D tex = new Texture2D(width, height, TextureFormat.RGB24, false); 

    Camera camera = GameObject.Find("Main Camera").GetComponent <Camera>(); 
    camera.targetTexture = rt; 
    camera.Render(); 

    RenderTexture.active = rt; 

    // Read screen contents into the texture 
    tex.ReadPixels(new Rect(0, 0, width, height), 0, 0); 
    camera.targetTexture = null; 
    RenderTexture.active = null; 
    Destroy(rt); 

    // Encode texture into JPG 
    byte[] bytes = tex.EncodeToJPG(); 
    Destroy(tex); 

    return bytes; 
} 

ich meine Daten dann serialisiert FlatBuffers mit:

public static byte[] FlatSerialize(this ServerToClientMessage message) { 
    var builder = new FlatBufferBuilder(1); 

    //Create an ID 
    var MessageId = builder.CreateString(message.MessageId.ToString()); 

    //Start the vector... 
    //Loop over each byte and add it - my god, is there not a better way? 
    FlatServerToClientMessage.StartImagebytesVector(builder, message.ImageBytes.Length); 
    foreach(var imageByte in message.ImageBytes) { 
    builder.AddByte(imageByte); 
    } 
    var imagebytes = builder.EndVector(); 

    //Start the FlatServerToClientMessage and add the MessageId and imagebytes 
    FlatServerToClientMessage.StartFlatServerToClientMessage(builder); 
    FlatServerToClientMessage.AddMessageid(builder, MessageId); 
    FlatServerToClientMessage.AddImagebytes(builder, imagebytes); 

    //End the FlatServerToClientMessage and finish it... 
    var flatMessage = FlatServerToClientMessage.EndFlatServerToClientMessage(builder); 
    FlatServerToClientMessage.FinishFlatServerToClientMessageBuffer(builder, flatMessage); 

    return builder.SizedByteArray(); 
} 

Als nächstes ich meine Daten senden

Zurück auf meinem Client-Gerät, lausche ich auf eingehende Daten, die deserialisiert und löst ein Ereignis t o das System auf die Ankunft eines neuen Bildes aufmerksam ...

private void Run() { 
    try { 
    // ShutdownEvent is a ManualResetEvent signaled by 
    // Client when its time to close the socket. 
    while (!ShutDownEvent.WaitOne(0)) { 
    try { 
    if (!_stream.DataAvailable) continue; 

    //Read the first 4 bytes which represent the size of the message, and convert from byte array to int32 
    var sizeinfo = new byte[4]; 
    _stream.Read(sizeinfo, 0, 4); 
    var messageSize = BitConverter.ToInt32(sizeinfo, 0); 

    //create a new buffer for the data to be read 
    var buffer = new byte[messageSize]; 

    var read = 0; 
    //Continue reading from the stream until we have read all bytes @messageSize 
    while (read != messageSize) { 
     read += _stream.Read(buffer, read, buffer.Length - read); 
    } 

    var message = new ServerToClientMessage().FlatDeserialize(buffer); 

    //raise data received event 
    OnDataReceived(message); 

    } catch (IOException ex) { 
    // Handle the exception... 
    } 
    } 
    } catch (Exception ex) { 
    // Handle the exception... 
    } finally { 
    _stream.Close(); 
    } 
} 

deserialisieren, ich folgendes:

public static ServerToClientMessage FlatDeserialize(this ServerToClientMessage message, byte[] bytes) { 

    var bb = new ByteBuffer(bytes); 
    var flatmessage = FlatServerToClientMessage.GetRootAsFlatServerToClientMessage(bb); 

    message.MessageId = new Guid(flatmessage.Messageid); 
    message.ImageBytes = new byte[flatmessage.ImagebytesLength]; 

    for (var i = 0; i < flatmessage.ImagebytesLength; i++) { 
    message.ImageBytes[i] = flatmessage.GetImagebytes(i); 
    } 

    return message; 
} 

Aus Gründen der Übersichtlichkeit ist hier die ServerToClientMessage Klasse:

public class ServerToClientMessage : EventArgs 
{ 
    public Guid MessageId { get; set; } 
    public byte[] ImageBytes { get; set; } 
} 

Wie auch immer, das Ereignis OnDataReceived wird ausgelöst und das wiederum ruft eine Funktion zum Konvertieren von dem Array ImageBytes in ein System.Drawing.Image auf. Diese Funktion ist hier:

public Image byteArrayToImage(byte[] byteArrayIn) { 
    // SAME PROBLEM! 
    //var converter = new System.Drawing.ImageConverter(); 
    // return (Image)converter.ConvertFrom(byteArrayIn); ; 

    using(var memoryStream = new MemoryStream(byteArrayIn)) { 
    return Image.FromStream(memoryStream, false, false); 
    } 
} 

Nun, meine Bilddaten vom Server gesendet werden, ist schön und gut ... ich habe es bestätigt. Das alles funktioniert auch, wenn ich JSON benutze. Ich habe viele Möglichkeiten versucht, von einem Bytearray in ein Bild zu konvertieren, aber ich scheine immer die Parameter is not valid Ausnahme zu erhalten. Ich habe auch versucht, mein Bild in verschiedenen Formaten wie JPG und PNG sowie rohen Pixeldaten zu senden.

Wer hat eine Idee?

Antwort

0

Ich habe es herausgefunden.

Es stellt sich heraus, dass die Daten rückwärts ... wegen FlatBuffers Serialisierung sind. Die Lösung ist, die Reihenfolge meiner for-loop während der Serialisierung umzukehren:

for (var i = message.ImageBytes.Length; i -->0;) 
{ 
    builder.AddByte(message.ImageBytes[i]); 
}