PageRenderTime 22ms CodeModel.GetById 16ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 0ms

/Aurora/Modules/World/Terrain/FileLoaders/GenericSystemDrawing.cs

https://bitbucket.org/VirtualReality/software-testing
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}