/Aurora/Modules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
C# | 233 lines | 126 code | 31 blank | 76 comment | 12 complexity | 3820ecdb12a917aeee89feaef232949b MD5 | raw file
1/* 2 * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/ 3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * * Neither the name of the Aurora-Sim Project nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28using Aurora.Framework; 29using System; 30using System.Drawing; 31using System.Drawing.Imaging; 32using System.IO; 33using Aurora.Framework.ConsoleFramework; 34using Aurora.Framework.Modules; 35using Aurora.Framework.SceneInfo; 36 37namespace Aurora.Modules.Terrain.FileLoaders 38{ 39 /// <summary> 40 /// A virtual class designed to have methods overloaded, 41 /// this class provides an interface for a generic image 42 /// saving and loading mechanism, but does not specify the 43 /// format. It should not be insubstantiated directly. 44 /// </summary> 45 public class GenericSystemDrawing : ITerrainLoader 46 { 47 #region ITerrainLoader Members 48 49 public string FileExtension 50 { 51 get { return ".gsd"; } 52 } 53 54 /// <summary> 55 /// Loads a file from a specified filename on the disk, 56 /// parses the image using the System.Drawing parsers 57 /// then returns a terrain channel. Values are 58 /// returned based on HSL brightness between 0m and 128m 59 /// </summary> 60 /// <param name="filename">The target image to load</param> 61 /// <param name="scene"></param> 62 /// <returns>A terrain channel generated from the image.</returns> 63 public virtual ITerrainChannel LoadFile(string filename, IScene scene) 64 { 65 return LoadBitmap(new Bitmap(filename)); 66 } 67 68 public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h) 69 { 70 // [[THEMAJOR]] Some work on tile loading.. 71 // terrain load-tile Tile.png 5 5 10000 10050 72 Bitmap tilemap = new Bitmap(filename); 73 74 // Prevents off-by-one issue 75 fileHeight--; 76 77 int xoffset = w*x; 78 int yoffset = h*(fileHeight - y); 79 80 //MainConsole.Instance.DebugFormat( 81 // "[TERRAIN]: Loading tile {0},{1} (offset {2},{3}) from tilemap size of {4},{5}", 82 // x, y, xoffset, yoffset, fileWidth, fileHeight); 83 84 Rectangle tileRect = new Rectangle(xoffset, yoffset, w, h); 85 PixelFormat format = tilemap.PixelFormat; 86 Bitmap cloneBitmap = null; 87 try 88 { 89 cloneBitmap = tilemap.Clone(tileRect, format); 90 } 91 catch (OutOfMemoryException e) 92 { 93 // This error WILL appear if the number of Y tiles is too high because of how it works from the bottom up 94 // However, this still spits out ugly unreferenced object errors on the console 95 MainConsole.Instance.ErrorFormat( 96 "[TERRAIN]: Couldn't load tile {0},{1} (from bitmap coordinates {2},{3}). Number of specified Y tiles may be too high: {4}", 97 x, y, xoffset, yoffset, e); 98 } 99 finally 100 { 101 // Some attempt at keeping a clean memory 102 tilemap.Dispose(); 103 } 104 105 return LoadBitmap(cloneBitmap); 106 } 107 108 public virtual ITerrainChannel LoadStream(Stream stream, IScene scene) 109 { 110 return LoadBitmap(new Bitmap(stream)); 111 } 112 113 /// <summary> 114 /// Exports a file to a image on the disk using a System.Drawing exporter. 115 /// </summary> 116 /// <param name="filename">The target filename</param> 117 /// <param name="map">The terrain channel being saved</param> 118 public virtual void SaveFile(string filename, ITerrainChannel map) 119 { 120 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 121 122 colours.Save(filename, ImageFormat.Png); 123 } 124 125 /// <summary> 126 /// Exports a stream using a System.Drawing exporter. 127 /// </summary> 128 /// <param name="stream">The target stream</param> 129 /// <param name="map">The terrain channel being saved</param> 130 public virtual void SaveStream(Stream stream, ITerrainChannel map) 131 { 132 Bitmap colours = CreateGrayscaleBitmapFromMap(map); 133 134 colours.Save(stream, ImageFormat.Png); 135 } 136 137 #endregion 138 139 protected virtual ITerrainChannel LoadBitmap(Bitmap bitmap) 140 { 141 ITerrainChannel retval = new TerrainChannel(bitmap.Width, bitmap.Height, null); 142 143 int x; 144 for (x = 0; x < bitmap.Width; x++) 145 { 146 int y; 147 for (y = 0; y < bitmap.Height; y++) 148 { 149 retval[x, y] = bitmap.GetPixel(x, bitmap.Height - y - 1).GetBrightness()*128; 150 } 151 } 152 153 return retval; 154 } 155 156 public override string ToString() 157 { 158 return "SYS.DRAWING"; 159 } 160 161 /// <summary> 162 /// Protected method, generates a grayscale bitmap 163 /// image from a specified terrain channel. 164 /// </summary> 165 /// <param name="map">The terrain channel to export to bitmap</param> 166 /// <returns>A System.Drawing.Bitmap containing a grayscale image</returns> 167 protected static Bitmap CreateGrayscaleBitmapFromMap(ITerrainChannel map) 168 { 169 Bitmap bmp = new Bitmap(map.Width, map.Height); 170 171 const int pallete = 256; 172 173 Color[] grays = new Color[pallete]; 174 for (int i = 0; i < grays.Length; i++) 175 { 176 grays[i] = Color.FromArgb(i, i, i); 177 } 178 179 for (int y = 0; y < map.Height; y++) 180 { 181 for (int x = 0; x < map.Width; x++) 182 { 183 // 512 is the largest possible height before colours clamp 184 int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y]/128.0), 0.0)*(pallete - 1)); 185 186 // Handle error conditions 187 if (colorindex > pallete - 1 || colorindex < 0) 188 bmp.SetPixel(x, map.Height - y - 1, Color.Red); 189 else 190 bmp.SetPixel(x, map.Height - y - 1, grays[colorindex]); 191 } 192 } 193 return bmp; 194 } 195 196 /// <summary> 197 /// Protected method, generates a coloured bitmap 198 /// image from a specified terrain channel. 199 /// </summary> 200 /// <param name="map">The terrain channel to export to bitmap</param> 201 /// <returns>A System.Drawing.Bitmap containing a coloured image</returns> 202 protected static Bitmap CreateBitmapFromMap(ITerrainChannel map) 203 { 204 Bitmap gradientmapLd = new Bitmap("defaultstripe.png"); 205 206 int pallete = gradientmapLd.Height; 207 208 Bitmap bmp = new Bitmap(map.Width, map.Height); 209 Color[] colours = new Color[pallete]; 210 211 for (int i = 0; i < pallete; i++) 212 { 213 colours[i] = gradientmapLd.GetPixel(0, i); 214 } 215 216 for (int y = 0; y < map.Height; y++) 217 { 218 for (int x = 0; x < map.Width; x++) 219 { 220 // 512 is the largest possible height before colours clamp 221 int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y]/512.0), 0.0)*(pallete - 1)); 222 223 // Handle error conditions 224 if (colorindex > pallete - 1 || colorindex < 0) 225 bmp.SetPixel(x, map.Height - y - 1, Color.Red); 226 else 227 bmp.SetPixel(x, map.Height - y - 1, colours[colorindex]); 228 } 229 } 230 return bmp; 231 } 232 } 233}