Q:

Bitmap from byte[] array

I want to create a bitmap from a byte[]. My problem is that I can't use a BitmapSource in Unity and if I use a MemoryStream Unity gets an error.
I tried it with this:
  Bitmap bitmap = new Bitmap(512, 424);

  var data = bitmap.LockBits(new Rectangle(Point.Empty, bitmap.Size),
  ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

  Marshal.Copy(arrayData, 0, data.Scan0, arrayData.Length);

  bitmap.UnlockBits(data);

It works but the Bitmap I get is the wrong way up. Can someone explain me why and got a solution for me?

A:

This can be two things, perhaps combined: The choice of coordinate system, and Endianness
There's a convention (I believe universal) to list pixels from left to right, but there's none regarding vertical orientation. While some programs and APIs have the Y-coordinate be zero at the bottom and increases upwards, others do the exact opposite. I don't know where you get the byte[] from, but some APIs allow you to configure the pixel orientation when writing, reading or using textures. Otherwise, you'll have to manually re-arrange the rows.
The same applies to endianness; ARGB sometimes means Blue is the last byte, sometimes the first.Some classes, like BitConverter have buit-in solutions too.
Unity uses big-endian, bottom-up textures. In fact, Unity handles lots of this stuff under the hood, and has to re-order rows and flip bytes when importing bitmap files. Unity also provides methods like LoadImage and EncodeToPNG that take care of both problems.
To illustrate what happens to the byte[], this sample code saves the same image in three different ways (but you need to import them as Truecolor to see them properly in Unity):
using UnityEngine;
using UnityEditor;
using System.Drawing;
using System.Drawing.Imaging;

public class CreateTexture2D : MonoBehaviour {

    public void Start () {

        int texWidth = 4, texHeight = 4;

        // Raw 4x4 bitmap data, in bottom-up big-endian ARGB byte order. It's transparent black for the most part.
        byte[] rawBitmap = new byte[] {

            // Red corner (bottom-left) is written first
            255,255,0,0,  0,0,0,0,      0,0,0,0,      0,0,0,0,
            0,0,0,0,      0,0,0,0,      0,0,0,0,      0,0,0,0,
            0,0,0,0,      0,0,0,0,      0,0,0,0,      0,0,0,0,
            255,0,0,255,  255,0,0,255,  255,0,0,255,  255,0,0,255
            //Blue border (top) is the last "row" of the array
        };

        // We create a Texture2D from the rawBitmap
        Texture2D texture = new Texture2D(texWidth, texHeight, TextureFormat.ARGB32, false);
        texture.LoadRawTextureData(rawBitmap);
        texture.Apply();

        // 1.- We save it directly as a Unity asset (btw, this is useful if you only use it inside Unity)
        UnityEditor.AssetDatabase.CreateAsset(texture, "Assets/TextureAsset.asset");

        // 2.- We save the texture to a file, but letting Unity handle formatting
        byte[] textureAsPNG = texture.EncodeToPNG();
        System.IO.File.WriteAllBytes(Application.dataPath + "/EncodedByUnity.png", textureAsPNG);

        // 3.- Rearrange the rawBitmap manually into a top-down small-endian ARGB byte order. Then write to a Bitmap, and save to disk.
        // Bonus: This permutation is it's own inverse, so it works both ways.
        byte[] rearrangedBM = new byte[rawBitmap.Length];
        for (int row = 0; row < texHeight; row++)
            for (int col = 0; col < texWidth; col++)
                for (int i = 0; i < 4; i++)
                    rearrangedBM[row * 4 * texWidth + 4 * col + i] = rawBitmap[(texHeight - 1 - row) * 4 * texWidth + 4 * col + (3 - i)];

        Bitmap bitmap = new Bitmap(texWidth, texHeight, PixelFormat.Format32bppArgb);
        var data = bitmap.LockBits(new Rectangle(0, 0, texWidth, texHeight), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
        System.Runtime.InteropServices.Marshal.Copy(rearrangedBM, 0, data.Scan0, rearrangedBM.Length);
        bitmap.UnlockBits(data);
        bitmap.Save(Application.dataPath + "/SavedBitmap.png", ImageFormat.Png);
    }
}

