System.Drawing.Image参数无效

时间:2016-08-08 12:48:40

标签: c# image unity3d

我知道这已经被多次询问了......我已经搜索过并尝试了所有我能做的事情,但我仍然不确定为什么我得到“参数无效”例外......

我有一个运行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...
  }
 }

回到我的客户端设备上,我正在侦听传入的数据,这些数据会反序列化并引发一个事件,以提醒系统新图像到达...

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,以及原始像素数据。

有人有想法吗?

1 个答案:

答案 0 :(得分:0)

想出来。

事实证明,由于FlatBuffers序列化,数据是向后的...... 解决方案是在序列化期间颠倒for-loop的顺序:

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