2016-08-08 14 views
0

これは何度も尋ねられてきたことを知っています...私はすべての検索と試行を行っていますが、なぜ "パラメータが有効ではありません"という例外...System.Drawing.Imageパラメータが無効

Windows Server 2012を実行しているAmazon EC2インスタンスがあります。そのマシンでは、Unity3D(Unity 5)を実行しています。そのUnityアプリケーションは、TCPを介してEC2インスタンスから私のローカルラップトップにフレーム(画像)を送信しています。私のクライアントはWindows 10を実行していますが、違いはありません。

私の画像データを取得するために、私は次のようにします。

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; 
} 

私はその後FlatBuffersを使って自分のデータをシリアル化:

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(); 
} 

次に、私は私のデータを送信します。

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... 
    } 
} 

私のクライアントデバイスに戻ると、デシリアライズしてイベントを発生させる受信データを聞いています。 Oデシリアライズするには

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(); 
    } 
} 

...新しいイメージの到着にシステムを警告、私は次のようにします。明確にするため

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; 
} 

、ここServerToClientMessageクラスがある:

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

とにかく、OnDataReceivedイベントが発生し、ImageBytes配列からSystem.Drawing.Imageに変換する関数が呼び出されます。その機能はここにあります:

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); 
    } 
} 

私の画像データはサーバから送られてきましたが、私はそれを検証しました。 JSONを使用すると、これはすべて正常に動作します。私は、バイト配列からImageに変換する多くの方法を試しましたが、私はいつもParameter is not valid例外を表示するようです。私はまた、JPGやPNGのようなさまざまなフォーマットで画像を送ろうとしました。

誰でも知っていますか?

答えて

0

それを実演しました。

FlatBuffersのシリアル化のために、データが後方にあることが判明しました。 解決方法は、シリアル化中に私のfor-loopの順番を逆にすることです:

for (var i = message.ImageBytes.Length; i -->0;) 
{ 
    builder.AddByte(message.ImageBytes[i]); 
} 
関連する問題