// Unity PNG encoder does not support 16bit export, change will come later 2019
        public static void ExportTerrainHeightsToTexture(TerrainData terrainData, Heightmap.Format format, string path)
        {
            RenderTexture oldRT   = RenderTexture.active;
            int           width   = terrainData.heightmapTexture.width - 1;
            int           height  = terrainData.heightmapTexture.height - 1;
            var           texture = new Texture2D(width, height, terrainData.heightmapTexture.graphicsFormat, TextureCreationFlags.None);

            RenderTexture.active = terrainData.heightmapTexture;
            texture.ReadPixels(new Rect(0, 0, width, height), 0, 0);
            texture.Apply();

            byte[] bytes;
            switch (format)
            {
            case Heightmap.Format.TGA:
                bytes = texture.EncodeToTGA();
                path  = path + ".tga";
                break;

            default:
                bytes = texture.EncodeToPNG();
                path  = path + ".png";
                break;
            }

            File.WriteAllBytes(path, bytes);
            RenderTexture.active = oldRT;
        }
        // Unity PNG encoder does not support 16bit export, change will come later 2019
        public static void ExportTerrainHeightsToTexture(TerrainData terrainData, Heightmap.Format format, string path, bool flipVertical, Vector2 inputLevelsRange)
        {
            RenderTexture oldRT   = RenderTexture.active;
            int           width   = terrainData.heightmapTexture.width - 1;
            int           height  = terrainData.heightmapTexture.height - 1;
            var           texture = new Texture2D(width, height, terrainData.heightmapTexture.graphicsFormat, TextureCreationFlags.None);

            RenderTexture.active = terrainData.heightmapTexture;
            texture.ReadPixels(new Rect(0, 0, width, height), 0, 0);

            //Remap Texture
            Color[] pixels = texture.GetPixels();
            for (int i = 0; i < pixels.Length; i += 4)
            {
                pixels[i].r     = (pixels[i].r * 2) * (inputLevelsRange.y - inputLevelsRange.x) + inputLevelsRange.x;
                pixels[i + 1].r = (pixels[i + 1].r * 2) * (inputLevelsRange.y - inputLevelsRange.x) + inputLevelsRange.x;
                pixels[i + 2].r = (pixels[i + 2].r * 2) * (inputLevelsRange.y - inputLevelsRange.x) + inputLevelsRange.x;
                pixels[i + 3].r = (pixels[i + 3].r * 2) * (inputLevelsRange.y - inputLevelsRange.x) + inputLevelsRange.x;
            }
            texture.SetPixels(pixels);
            texture.Apply();

            //Flip Texture
            if (flipVertical)
            {
                ToolboxHelper.FlipTexture(texture, true);
            }

            byte[] bytes;
            switch (format)
            {
            case Heightmap.Format.TGA:
                bytes = texture.EncodeToTGA();
                path  = path + ".tga";
                break;

            default:
                bytes = texture.EncodeToPNG();
                path  = path + ".png";
                break;
            }

            File.WriteAllBytes(path, bytes);
            RenderTexture.active = oldRT;
        }
        public void TerrainToolboxUtilites_WhenExportHeightmap_LevelCorrectionWorks(float min, float max, Heightmap.Format format, Heightmap.Depth depth = Heightmap.Depth.Bit16)
        {
            TerrainToolboxWindow toolboxWindow   = EditorWindow.GetWindow(typeof(TerrainToolboxWindow)) as TerrainToolboxWindow;
            Texture2D            gradientTexture = CreateGradientTexture();

            int heightmapResolution = 513;
            int numberOfTiles       = 1;
            int baseLevel           = 0;
            int remapLevel          = 1;

            ToolboxHelper.CopyTextureToTerrainHeight(m_TerrainComponent.terrainData, gradientTexture, Vector2Int.zero, heightmapResolution, numberOfTiles, baseLevel, remapLevel);

            Selection.activeGameObject = m_TerrainGO;
            m_TerrainGO.name           = "TestTerrain";
            m_TerrainComponent.name    = "TestComponent";

            RenderTexture oldRT = RenderTexture.active;

            RenderTexture.active = m_TerrainComponent.terrainData.heightmapTexture;

            //Run Tests and Cleanup files
            string fileName = m_TerrainGO.name + "_heightmap";
            string path     = Path.Combine(toolboxWindow.m_TerrainUtilitiesMode.m_Settings.HeightmapFolderPath, fileName);

            switch (format)
            {
            case Heightmap.Format.PNG:
                path += ".png";
                Assert.IsTrue(TestLevelCorrection(toolboxWindow, new Vector2(min, max), path, format));
                FileUtil.DeleteFileOrDirectory(path);
                FileUtil.DeleteFileOrDirectory(path + ".meta");
                break;

            case Heightmap.Format.TGA:
                path += ".tga";
                Assert.IsTrue(TestLevelCorrection(toolboxWindow, new Vector2(min, max), path, format));
                FileUtil.DeleteFileOrDirectory(path);
                FileUtil.DeleteFileOrDirectory(path + ".meta");
                break;

            case Heightmap.Format.RAW:
                path += ".raw";
                Assert.IsTrue(TestLevelCorrection(toolboxWindow, new Vector2(min, max), path, depth));
                FileUtil.DeleteFileOrDirectory(path);
                FileUtil.DeleteFileOrDirectory(path + ".meta");
                break;
            }

            AssetDatabase.Refresh();
            RenderTexture.active = oldRT;
            toolboxWindow.Close();
        }
        /// <summary>
        /// This overloaded method deals specifically with testing the level correction of the png and tga format
        /// </summary>
        /// <param name="toolboxWindow">Window where the Export Heightmap Utilities live</param>
        /// <param name="minMaxRemap">Min and Max values of the remap</param>
        /// <param name="path">String path of the files directory location</param>
        /// <param name="format">Heightmap File Format</param>
        /// <returns></returns>
        bool TestLevelCorrection(TerrainToolboxWindow toolboxWindow, Vector2 minMaxRemap, string path, Heightmap.Format format)
        {
            //Execute the repro steps in code
            toolboxWindow.m_TerrainUtilitiesMode.m_Settings.ExportHeightRemapMin = minMaxRemap.x;
            toolboxWindow.m_TerrainUtilitiesMode.m_Settings.ExportHeightRemapMax = minMaxRemap.y;

            toolboxWindow.m_TerrainUtilitiesMode.m_Settings.HeightFormat = format;
            toolboxWindow.m_TerrainUtilitiesMode.ExportHeightmaps(new Object[] { m_TerrainComponent });

            //Get heightmap data to compare
            int width   = RenderTexture.active.width - 1;
            int height  = RenderTexture.active.height - 1;
            var texture = new Texture2D(width, height, RenderTexture.active.graphicsFormat, UnityEngine.Experimental.Rendering.TextureCreationFlags.None);

            texture.ReadPixels(new Rect(0, 0, width, height), 0, 0);

            //Remap Texture
            Color[] pixels = texture.GetPixels();
            for (int i = 0; i < pixels.Length; i += 4)
            {
                pixels[i].r     = (pixels[i].r * 2) * (minMaxRemap.y - minMaxRemap.x) + minMaxRemap.x;
                pixels[i + 1].r = (pixels[i + 1].r * 2) * (minMaxRemap.y - minMaxRemap.x) + minMaxRemap.x;
                pixels[i + 2].r = (pixels[i + 2].r * 2) * (minMaxRemap.y - minMaxRemap.x) + minMaxRemap.x;
                pixels[i + 3].r = (pixels[i + 3].r * 2) * (minMaxRemap.y - minMaxRemap.x) + minMaxRemap.x;
            }
            texture.SetPixels(pixels);
            texture.Apply();

            //Compare both the original and regression test data
            byte[] byteData = File.ReadAllBytes(path);
            return(format == Heightmap.Format.PNG ?
                   texture.EncodeToPNG().SequenceEqual(byteData) :
                   texture.EncodeToTGA().SequenceEqual(byteData));
        }