public static void LoadRawFileAsTexture(string rawFile, Texture2D output, HeightfileFormat format)
    {
        if (!File.Exists(rawFile))
        {
            throw new FileNotFoundException("Raw file does not exist: " + rawFile);
        }

        // Open filestream and read into bytebuffer
        byte[] bytes      = File.ReadAllBytes(rawFile);
        int    resolution = GetHeightmapResolution(bytes, format);

        ValidateHeightmapRaw(bytes, output.width, format);

        //Texture2D tex = new Texture2D(resolution, resolution, TextureFormat.ARGB32, true);

        // Prepare colorbuffer
        Color[] pixels = new Color[resolution * resolution];

        // Parse bytebuffer into colors, taking care of mirroring and byte format
        int i = 0;
        int j = 0;

        for (int x = 0; x < resolution; x++)
        {
            for (int y = 0; y < resolution; y++)
            {
                float gray;
                switch (format)
                {
                case HeightfileFormat.R8:
                    gray        = bytes[i++] / 256f;
                    pixels[j++] = new Color(gray, gray, gray);
                    break;

                case HeightfileFormat.Windows:
                    gray        = (bytes[i++] + bytes[i++] * 256f) / 65535f;
                    pixels[j++] = new Color(gray, gray, gray);
                    break;

                case HeightfileFormat.Mac:
                    gray        = (bytes[i++] * 256.0f + bytes[i++]) / 65535f;
                    pixels[j++] = new Color(gray, gray, gray);
                    break;
                }
            }
        }

        output.SetPixels(pixels);
    }
    private static void ValidateHeightmapRaw(byte[] input, int outputResolution, HeightfileFormat format)
    {
        int bytesPerPixel   = (format == HeightfileFormat.R8 ? 1 : 2);
        int inputResolution = GetHeightmapResolution(input, format);
        int inputPixels     = inputResolution * inputResolution * bytesPerPixel;

        if (inputResolution != outputResolution)
        {
            throw new ArgumentException(String.Format("The input file resolution {0} does not match the output resolution {1}", inputResolution, outputResolution));
        }

        if (input.Length != inputPixels)
        {
            throw new ArgumentException("The specified HeightFileFormat does not match the file. Expected size does not match.");
        }
    }
    public static void LoadRawFileAsFloats(string fileName, ref float[,] output, HeightfileFormat format, bool flipX, bool flipY)
    {
        if (!File.Exists(fileName))
        {
            throw new FileNotFoundException("Heightmap file does not exist: " + fileName);
        }

        // Todo: we allocate a byte array, and then a float array. Can we do allocation for just one, and then reinterpret?

        byte[] input      = File.ReadAllBytes(fileName);
        int    resolution = GetHeightmapResolution(input, format);

        ValidateHeightmapRaw(input, output.GetLength(0), format);

        // Parse bytebuffer into floats, taking care of mirroring and byte format

        // Todo: replace in-loop switch with a Func<> lookup to avoid branching

        int i = 0;

        for (int x = 0; x < resolution; x++)
        {
            for (int y = 0; y < resolution; y++)
            {
                int iX = flipY ? resolution - 1 - x : x;
                int iY = flipX ? resolution - 1 - y : y;

                switch (format)
                {
                case HeightfileFormat.R8:
                    output[iX, iY] = input[i++] / 256f;
                    break;

                case HeightfileFormat.Windows:
                    output[iX, iY] = (input[i++] + input[i++] * 256f) / 65535f;
                    break;

                case HeightfileFormat.Mac:
                    output[iX, iY] = (input[i++] * 256.0f + input[i++]) / 65535f;
                    break;
                }
            }
        }
    }
    public static void ParseHeightmapFileToTerrain(string path, TerrainData terrainData, HeightfileFormat format, bool flipX, bool flipY)
    {
        if (path == "")
        {
            Debug.LogError("Path is empty");
            return;
        }

        if (terrainData == null)
        {
            Debug.LogError("Terraindata is null");
            return;
        }

        var heightData = new float[terrainData.heightmapWidth, terrainData.heightmapWidth];

        LoadRawFileAsFloats(path, ref heightData, format, flipX, flipY);

        if (heightData != null)
        {
            terrainData.SetHeights(0, 0, heightData);
        }
    }
    public static int GetHeightmapResolution(byte[] bytes, HeightfileFormat format)
    {
        int bytesPerPixel = (format == HeightfileFormat.R8 ? 1 : 2);

        return((int)Math.Sqrt(bytes.Length / bytesPerPixel));
    }