/// <summary>
        /// Creates a Terr heightmap from a Bitmap
        /// </summary>
        /// <param name="oldTerr">Source terr</param>
        /// <param name="heightmap">Heightmap Bitmap</param>
        /// <param name="targetHmaps">Flags to determine which Heightmaps shall be changed</param>
        /// <returns></returns>
        public static Terr FromBitmap(this Terr oldTerr, Bitmap heightmap, TargetHeightmaps targetHmaps)
        {
            if (heightmap.Width != oldTerr.Width || heightmap.Height != oldTerr.Height)
            {
                throw new ArgumentException(
                    "Heightmap measures wrong. Expected: " + oldTerr.Width + "x" + oldTerr.Height +
                    " (Image: " + heightmap.Width + "x" + heightmap.Height + ")");
            }
            if ((targetHmaps & (TargetHeightmaps.FirstHeightmap | TargetHeightmaps.SecondHeightmap)) == TargetHeightmaps.None)
            {
                throw new ArgumentException("No valid TargetHeightmap specified");
            }

            oldTerr = oldTerr.Decompress();

            bool keepFirstHmap = (targetHmaps & TargetHeightmaps.FirstHeightmap) == TargetHeightmaps.None;
            bool keepSecondHmap = (targetHmaps & TargetHeightmaps.SecondHeightmap) == TargetHeightmaps.None;

            Terr newTerr = new Terr();
            newTerr.Width = oldTerr.Width;
            newTerr.Height = oldTerr.Height;

            if (keepFirstHmap)
            {
                oldTerr.CopyFirstHmap(newTerr);
            }

            // This scary loop iterates row by row over all 8x8 blocks
            for (int h = 0; h < heightmap.Height; h += 8)
            {
                for (int w = 0; w < heightmap.Width; w += 8)
                {
                    // Single 8x8 Block
                    Terrblock block = new Terrblock();
                    if (!keepFirstHmap)
                    {
                        newTerr.BlocksHmap1.Add(block);
                    }
                    if (!keepSecondHmap)
                    {
                        newTerr.BlocksHmap2.Add(block);
                    }
                    int minHeight = int.MaxValue;
                    byte[] newOffsets = new byte[64];
                    for (int y = 0; y < 8; ++y)
                    {
                        if (h + y >= heightmap.Height)
                        {   // Image height not multiple of 8
                            break;
                        }
                        for (int x = 0; x < 8; ++x)
                        {
                            if (w + x >= heightmap.Width)
                            {   // Image width not multiple of 8
                                break;
                            }
                            int height = heightmap.GetPixel(w + x, h + y).R;
                            minHeight = Math.Min(minHeight, height);
                            newOffsets[x + y * 8] = (byte)height;
                        }
                    }
                    // Adjust offsets based on minimum
                    for (int i = 0; i < 64; ++i)
                    {
                        newOffsets[i] -= (byte)(minHeight);
                    }
                    // Scale to 65535 (65535 / 255 = 257)
                    minHeight *= 257;

                    newTerr.Offsets.Add(newOffsets);
                    block.Minimum = minHeight;
                    block.OffsetIndex = newTerr.Offsets.Count - 1;
                }
            }

            if (keepSecondHmap)
            {
                oldTerr.CopySecondHmap(newTerr);
            }

            return newTerr;
        }
        public static Bitmap ToBitmap(this Terr oldTerr, TargetHeightmaps targetHmaps, SmoothingAlgorithm salg)
        {
            bool firstHeightmap = (targetHmaps & TargetHeightmaps.FirstHeightmap) == TargetHeightmaps.FirstHeightmap;
            bool secondHeightmap = (targetHmaps & TargetHeightmaps.SecondHeightmap) == TargetHeightmaps.SecondHeightmap;

            if (firstHeightmap && secondHeightmap)
            {
                throw new ArgumentException("Both TargetHeightmaps specified");
            }
            else if (!firstHeightmap && !secondHeightmap)
            {
                throw new ArgumentException("No valid TargetHeightmaps specified");
            }

            IList<Terrblock> blocks;
            if (firstHeightmap)
            {
                blocks = oldTerr.BlocksHmap1;
            }
            else
            {
                blocks = oldTerr.BlocksHmap2;
            }

            Bitmap heightmap = new Bitmap(oldTerr.Width, oldTerr.Height);

            // This scary loop iterates row by row over all 8x8 blocks
            int row = 0;
            int col = 0;
            for (int i = 0; i < blocks.Count; ++i)
            {
                Terrblock block = blocks[i];
                byte[] offsets = oldTerr.Offsets[block.OffsetIndex];

                ++col;
                if (col * 8 >= heightmap.Width)
                {
                    col = 0;
                    row++;
                }

                // Single 8x8 Block
                for (int y = 0; y < 8; ++y)
                {
                    int targetY = row * 8 + y;

                    if (targetY >= heightmap.Height)
                    {
                        break;
                    }
                    for (int x = 0; x < 8; ++x)
                    {
                        int targetX = col * 8 + x;

                        if (targetX >= heightmap.Width)
                        {
                            break;
                        }

                        Color color;
                        if (salg == SmoothingAlgorithm.Default)
                        {
                            // Downscale from 65535 Minimum to 255 color space
                            int c = offsets[x + y * 8] + block.Minimum / 257;
                            color = Color.FromArgb(c, c, c);
                        }
                        else if (salg == SmoothingAlgorithm.Rob)
                        {
                            // Robs heightmap smoothing code
                            int c = 20 + ((offsets[x + y * 8] * 128 + block.Minimum) / 1024) * 2;
                            color = Color.FromArgb(c, c, c);
                        }
                        else
                        {
                            throw new ArgumentException("Unsupported Smoothing Algorithm");
                        }

                        heightmap.SetPixel(targetX, targetY, color);
                    }
                }
            }

            return heightmap;
        }