简体   繁体   English

System.Drawing.Image参数无效

[英]System.Drawing.Image Parameter Not Valid

I know this has been asked numerous times... and I have searched and tried everything that I can, but I am still not sure why I get the "parameter is not valid" exception... 我知道这个问题已经被问了无数次了……我已经搜索并尝试了所有可以尝试的方法,但是我仍然不确定为什么会出现“参数无效”的异常情况……

I have an Amazon EC2 instance running Windows Server 2012. On that machine, I am running Unity3D (Unity 5). 我有一个运行Windows Server 2012的Amazon EC2实例。在该计算机上,我正在运行Unity3D (Unity 5)。 That Unity application is sending frames (images) from the EC2 instance to my local laptop, via TCP. 该Unity应用程序正在通过TCP从EC2实例向我的本地笔记本电脑发送帧(图像)。 My client is running Windows 10, not that it is likely to make any difference. 我的客户端运行的是Windows 10,但可能不会有所不同。

To get my image data, I do the following: 要获取图像数据,请执行以下操作:

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

I then serialize my data using FlatBuffers : 然后,我使用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();
 }

Next, I send my data: 接下来,我发送数据:

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

Back on my client device, I am listening for incoming data which deserializes and raises an event to alert the system to the arrival of a new image... 回到我的客户端设备上,我正在侦听传入的数据,这些数据反序列化并引发一个事件,以提醒系统新图像的到来...

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

To deserialize, I do the following: 要反序列化,请执行以下操作:

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

For clarity, here is the ServerToClientMessage class: 为了清楚起见,这是ServerToClientMessage类:

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

Anyway, next, the OnDataReceived event gets raised and that in turn calls a function to convert from the ImageBytes array to a System.Drawing.Image. 无论如何,接下来,将OnDataReceived事件,并依次调用一个函数,以从ImageBytes数组转换为System.Drawing.Image。 That function is here: 该功能在这里:

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

Now, my image data being sent from the server is fine and dandy... I have validated it. 现在,从服务器发送的我的图像数据很好,很漂亮……我已经对其进行了验证。 This all works fine when I use JSON, too. 当我使用JSON时,这一切也都很好。 I've tried many ways to convert from a byte array to an Image, but I always seem to get the Parameter is not valid exception. 我尝试了多种方法将字节数组转换为Image,但是我似乎总是得到Parameter is not valid exception。 I've also tried sending my image in different formats like JPG and PNG, as well as raw pixel data. 我还尝试过以JPG和PNG等不同格式以及原始像素数据发送图像。

Anyone have an idea? 有人有主意吗?

Figured it out. 弄清楚了。

It turns out that the data is backwards...due to FlatBuffers serialization. 事实证明,由于FlatBuffers序列化,数据是向后的。 The solution is to reverse the order of my for-loop during serialization: 解决方案是在序列化过程中反转我的for-loop的顺序:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM