8

What would be a fast method to copy/convert an array of Color32[] values to a byte[] buffer? Color32 is a struct from Unity 3D containing 4 bytes, R, G, B and A respectively. What I'm trying to accomplish is to send the rendered image from unity through a pipe to another application (Windows Forms). Currently I'm using this code:

private static byte[] Color32ArrayToByteArray(Color32[] colors)
{
    int length = 4 * colors.Length;
    byte[] bytes = new byte[length];
    IntPtr ptr = Marshal.AllocHGlobal(length);
    Marshal.StructureToPtr(colors, ptr, true);
    Marshal.Copy(ptr, bytes, 0, length);
    Marshal.FreeHGlobal(ptr);
    return bytes;
}

Thankyou and sorry, I'm new to StackOverflow. Marinescu Alexandru

7
  • So you've got that code... does it do what you want it to? Commented Feb 2, 2014 at 15:25
  • Would you please share your result, problems and your question clearly?! Commented Feb 2, 2014 at 15:26
  • It would seem so. But I was wondering whether a faster method exists... Commented Feb 2, 2014 at 15:27
  • Any speed gain in mind? Commented Feb 2, 2014 at 15:34
  • I'm sending every frame rendered from Unity through a pipe to another application. That's why I wanted to know whether a faster method exists. Currently I'm getting around 11 msec per frame for converting the Color32[] array to a byte[] array. Previously I used the EncodeToPNG() method which took around 85 msec per frame. Commented Feb 2, 2014 at 15:40

3 Answers 3

11

I ended up using this code:

using System.Runtime.InteropServices;

private static byte[] Color32ArrayToByteArray(Color32[] colors)
{
    if (colors == null || colors.Length == 0)
        return null;

    int lengthOfColor32 = Marshal.SizeOf(typeof(Color32));
    int length = lengthOfColor32 * colors.Length;
    byte[] bytes = new byte[length];

    GCHandle handle = default(GCHandle);
    try
    {
        handle = GCHandle.Alloc(colors, GCHandleType.Pinned);
        IntPtr ptr = handle.AddrOfPinnedObject();
        Marshal.Copy(ptr, bytes, 0, length);
    }
    finally
    {
        if (handle != default(GCHandle))
            handle.Free();
    }

    return bytes;
}

Which is fast enough for my needs.

Sign up to request clarification or add additional context in comments.

1 Comment

i used this script to make a webcam screenshot method: static byte[] ScreenshotWebcam(WebCamTexture wct) { Texture2D colorTex = new Texture2D(wct.width, wct.height, TextureFormat.RGBA32, false); colorTex.LoadRawTextureData(Color32ArrayToByteArray(wct.GetPixels32())); colorTex.Apply(); return colorTex.EncodeToPNG(); }
4

With modern .NET, you can use spans for this:

var bytes = MemoryMarshal.Cast<Color32, byte>(colors);

This gives you a Span<byte> that covers the same data. The API is directly comparable to using vectors (byte[]), but it isn't actually a vector, and there is no copy: you are directly accessing the original data. It is like an unsafe pointer coercion, but: entirely safe.

If you need it as a vector, ToArray and copy methods exist for that.

Comments

-2

Well why do you work with Color32?

byte[] Bytes = tex.GetRawTextureData(); . . . Tex.LoadRawTextureData(Bytes); Tex.Apply();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.