/// <summary>
 /// Initializes a new instance of an AssetTexture object
 /// </summary>
 /// <param name="image">A <seealso cref="ManagedImage"/> object containing texture data</param>
 public AssetTexture(ManagedImage image)
 {
     Image = image;
     Components = 0;
     if ((Image.Channels & ManagedImage.ImageChannels.Color) != 0)
         Components += 3;
     if ((Image.Channels & ManagedImage.ImageChannels.Gray) != 0)
         ++Components;
     if ((Image.Channels & ManagedImage.ImageChannels.Bump) != 0)
         ++Components;
     if ((Image.Channels & ManagedImage.ImageChannels.Alpha) != 0)
         ++Components;
 }
Esempio n. 2
0
        private void DisplayResource(string resource)
        {
            Stream stream = OpenMetaverse.Helpers.GetResourceStream(resource + ".tga");

            if (stream != null)
            {
                AlphaMask = LoadTGAClass.LoadTGA(stream);
                stream.Close();

                ManagedImage managedImage = new ManagedImage(AlphaMask);

                // FIXME: Operate on ManagedImage instead of Bitmap
                pic1.Image = Oven.ModifyAlphaMask(AlphaMask, (byte)scrollWeight.Value, 0.0f);
            }
            else
            {
                MessageBox.Show("Failed to load embedded resource \"" + resource + "\"", "Baker",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
Esempio n. 3
0
        public void Decode_jp2k(string filename, string decodeType, Asset asset)
        {
            var img = (AssetTexture)asset;

            OpenMetaverse.Imaging.ManagedImage imgImage = img.Image;
            if (imgImage == null)
            {
                OpenJPEG.DecodeToImage(asset.AssetData, out imgImage);
            }
            if (imgImage != null)
            {
                if (filename.ToLower().EndsWith("tga"))
                {
                    File.WriteAllBytes(filename, imgImage.ExportTGA());
                }
                else
                {
                    File.WriteAllBytes(filename, imgImage.ExportRaw());
                }
            }
        }
Esempio n. 4
0
        private void ApplyTint(ManagedImage dest, Color4 src)
        {
            if (dest == null) return;

            for (int i = 0; i < dest.Red.Length; i++)
            {
                dest.Red[i] = (byte)((dest.Red[i] * Utils.FloatToByte(src.R, 0f, 1f)) >> 8);
                dest.Green[i] = (byte)((dest.Green[i] * Utils.FloatToByte(src.G, 0f, 1f)) >> 8);
                dest.Blue[i] = (byte)((dest.Blue[i] * Utils.FloatToByte(src.B, 0f, 1f)) >> 8);
            }
        }
Esempio n. 5
0
 public ManagedImage Clone()
 {
     ManagedImage image = new ManagedImage(Width, Height, Channels);
     if (Red != null) image.Red = (byte[])Red.Clone();
     if (Green != null) image.Green = (byte[])Green.Clone();
     if (Blue != null) image.Blue = (byte[])Blue.Clone();
     if (Alpha != null) image.Alpha = (byte[])Alpha.Clone();
     if (Bump != null) image.Bump = (byte[])Bump.Clone();
     return image;
 }
Esempio n. 6
0
        /// <summary>
        /// This method will produce a random city with the central region of the city being
        /// specified as a parameter. More parameters need to be made available for this method
        /// to produce a better quality city, note for now the minimum area for a city is a
        /// 3x3 grid of regions. This code is based on the original C++ version called pixel city.
        /// </summary>
        /// <param name="seed_value">Random integer seed value.</param>
        /// <returns>true / false indicator of success or failure.</returns>
        private bool doGenerate(int seed_value)
        {
            int rx, ry;
            //  Based on the initial seed value populate the regions that this shared module
            // is connected to, this means first get a list of the region, determine which
            // region is in the center of all the regions and set this as the hotzone, or
            // central part of the city (this is where the tallest/largest buildings will
            // be created) and will extend out to cover virtually all of the connected
            // regions if desired. No support for aging of the buildings or the city exists
            // yet it is a possible course for the future of this module.

            //  TODO
            //
            //      Validate the details in the configuration file against the settings in
            // the database, otherwise a new user/estate/parcel could be created which will
            // negate any of the security systems that Aurora has in place.

            //  First quick check to see if the module is enabled or not.
            if (!m_fEnabled)
            {
                m_log.Info("[CITY BUILDER]: Disabled, aborting auto generation.");
                return (false);
            }

            m_log.Info("[CITY BUILDER]: Auto generating the city.");

            //  Now we need to ask some basic values for the city generation, we already have
            // the base seed value as this is part of the 'city generate' command, now what
            // about a name, position, size, densities etc. Some of this can be generated
            // based on the seed value, but then, it would need to be confirmed by the user
            // or allow them to change it. TODO move all requested data into the configuration file.
            if (m_UserAccountService == null)
            {
                m_UserAccountService = simulationBase.ApplicationRegistry.RequestModuleInterface<IUserAccountService>();
            }

            //  Decide where the city is to be placed within the server instance.
            int r = CityModule.randomValue(10);

            string regionCount = MainConsole.Instance.CmdPrompt("Region Count ", r.ToString());
            r = Convert.ToInt32(regionCount);
            m_log.InfoFormat("[CITY BUILDER]: City area {0} x {1} regions ", r, r);

            //  Needs to be changed to use the 'defualt' properties and ask about the default
            // estate settings that are to be used, even if it is nothing more than just a
            // confirmation of the settings that are in the configuration file.
            cityName = MainConsole.Instance.CmdPrompt("City Name ", cityName);
            cityOwner = MainConsole.Instance.CmdPrompt("City Owner ", cityOwner);
            m_DefaultUserName = cityOwner;

            //  Make sure that the user and estate information specified in the configuration file
            // have been loaded and the information has either been found or has been created.
            m_DefaultUserAccount = m_UserAccountService.GetUserAccount(UUID.Zero, cityOwner);
            if (m_DefaultUserAccount == null)
            {
                m_log.InfoFormat("[CITY BUILDER]: Creating default account {0}", m_DefaultUserName);
                m_UserAccountService.CreateUser(m_DefaultUserName, Util.Md5Hash(m_DefaultUserPword), m_DefaultUserEmail);
                m_DefaultUserAccount = m_UserAccountService.GetUserAccount(UUID.Zero, m_DefaultUserName);
                cityOwner = m_DefaultUserName;
            }
            else
                m_log.InfoFormat("[CITY BUILDER]: Account found for {0}", m_DefaultUserName);

            // Obtain the scene manager that the server instance is using.
            sceneManager = simulationBase.ApplicationRegistry.RequestModuleInterface<SceneManager>();

            //  Construct the data instance for a city map to hold the total regions in the simulation.
            cityMap = new CityMap();
            citySeed = seed_value;
            cityMap.cityRegions = new Scene[r, r];
            cityMap.cityPlots = new List<BuildingPlot>();
            cityMap.cityBuildings = new List<CityBuilding>();

            //  Construct land and estate data and update to reflect the found user or the newly created one.
            cityLandData = new LandData();
            RegionInfo regionInfo = new RegionInfo();

            regionInfo.RegionID = UUID.Random();

            //  Determine if the default user account as specified in City Builder's configuration file
            // has any predefined estates, if so, just select the first one for now. Perhaps a search of
            // the estates to attempt to find a match to the details from the configuration file.
            EstateConnector = Aurora.DataManager.DataManager.RequestPlugin<IEstateConnector>();
            // Valid estate connection established.
            if (EstateConnector != null)
            {
                //  Valid estate connector, determine if the default user account has any estates.
                List<EstateSettings> estates = EstateConnector.GetEstates(m_DefaultUserAccount.PrincipalID);
                // No estates are found, so construct a new one based on the default estate settings
                // from the configuration file.
                if (estates == null)
                {
                    // No estates present so construct one.
                    m_DefaultEstate = new EstateSettings();

                    m_log.InfoFormat("[CITY BUILDER]: No estates found for user {0}, constructing default estate.", m_DefaultUserAccount.Name);

                    m_DefaultEstate.EstateOwner = m_DefaultUserAccount.PrincipalID;
                    m_DefaultEstate.EstateName = m_DefaultEstateName;
                    m_DefaultEstate.EstatePass = Util.Md5Hash(Util.Md5Hash(m_DefaultEstatePassword));
                    m_DefaultEstate.EstateID = (uint)CityModule.randomValue(1000);

                    regionInfo.EstateSettings = EstateConnector.CreateEstate(m_DefaultEstate, regionInfo.RegionID);
                }
                else
                {
                    //  Estates have been found, select the first estate in the list. No checking is done
                    // against the configuration file settings. TODO validate the estate against the
                    // configuration file.
                    m_DefaultEstate = estates[0];
                    regionInfo.EstateSettings = m_DefaultEstate;
                    m_log.InfoFormat("[CITY BUILDER]: {0} estates found for user {1}, selecting {2}",
                        estates.Count, m_DefaultUserAccount.Name, m_DefaultEstate.EstateName);
                }
            }
            else
            {
                m_log.Info("[CITY BUILDER]: No connection with server.");
                return (false);
            }

            //  Fill in land data for the estate/owner.
            cityLandData.OwnerID = m_DefaultUserAccount.PrincipalID;
            cityLandData.Name = m_DefaultEstateName;
            cityLandData.GlobalID = UUID.Random();
            cityLandData.GroupID = UUID.Zero;

            int regionPort = startPort;

            //  Construct the region.
            regionInfo.RegionSizeX = cityConfig.GetInt("DefaultRegionSize", 256);
            regionInfo.RegionSizeY = regionInfo.RegionSizeX;
            regionInfo.RegionType = "Mainland";
            regionInfo.ObjectCapacity = 100000;
            regionInfo.Startup = StartupType.Normal;
            regionInfo.ScopeID = UUID.Zero;

            IParcelServiceConnector parcelService = simulationBase.ApplicationRegistry.RequestModuleInterface<IParcelServiceConnector>();
            if (parcelService == null)
            {
                m_log.Info("[CITY BUILDER]: Unable to connect to servers parcel service.");
            }

            if (r == 1)
            {
                m_log.Info("[CITY BUILDER]: Single region city.");
                IPAddress address = IPAddress.Parse("0.0.0.0");
                regionInfo.ExternalHostName = Aurora.Framework.Utilities.GetExternalIp();
                regionInfo.FindExternalAutomatically = true;
                regionInfo.InternalEndPoint = new IPEndPoint(address, regionPort++);
                cityLandData.RegionID = regionInfo.RegionID;
                regionInfo.RegionName = "Region00";
                regionInfo.RegionLocX = (int)m_DefaultStartLocation.X;
                regionInfo.RegionLocY = (int)m_DefaultStartLocation.Y;
                if (parcelService != null)
                    parcelService.StoreLandObject(cityLandData);
                if (!createRegion(0, 0, regionInfo))
                {
                    m_log.Info("[CITY BUILDER]: Failed to construct region.");
                    return (false);
                }
            }
            else if (r > 1)
            {
                m_log.Info("[CITY BUILDER]: Multi-region city.");
                m_log.Info("[CITY BUILDER]: Finding external IP, please wait ... ");
                regionInfo.ExternalHostName = Aurora.Framework.Utilities.GetExternalIp();
                if (regionInfo.ExternalHostName.Length <= 0)
                {
                    regionInfo.FindExternalAutomatically = false;
                }
                else
                {
                    m_log.InfoFormat("[CITY BUILDER]: External IP address is {0}", regionInfo.ExternalHostName);
                    regionInfo.FindExternalAutomatically = true;
                }
                //  Construct the regions for the city.
                regionPort = startPort;
                INeighborService neighbours = simulationBase.ApplicationRegistry.RequestModuleInterface<INeighborService>();
                if (neighbours == null)
                {
                    m_log.Info("[CITY BUILDER]: No neighbours.");
                }
                else
                {
                    m_log.Info("[CITY BUILDER]: Neighbours service found.");
                }
                IPAddress address = IPAddress.Parse("0.0.0.0");

                for (rx = 0; rx < r; rx++)
                {
                    for (ry = 0; ry < r; ry++)
                    {
                        regionInfo.InternalEndPoint = new IPEndPoint(address, regionPort++);
                        cityLandData.RegionID = regionInfo.RegionID;
                        regionInfo.RegionName = "Region" + rx + ry;
                        regionInfo.RegionLocX = (int)(m_DefaultStartLocation.X + rx);
                        regionInfo.RegionLocY = (int)(m_DefaultStartLocation.Y + ry);
                        m_log.InfoFormat("[CITY BUILDER]: '{0}' @ {1},{2}, http://{3}/", regionInfo.RegionName,
                            regionInfo.RegionLocX, regionInfo.RegionLocY, regionInfo.InternalEndPoint);
                        if (parcelService != null)
                            parcelService.StoreLandObject(cityLandData);
                        if (!createRegion(rx, ry, regionInfo))
                        {
                            m_log.InfoFormat("[CITY BUILDER]: Failed to construct region at {0},{1}", rx, ry);
                            return (false);
                        }
                        if (neighbours != null)
                        {
                            m_log.Info("[CITY BUILDER]: Informing neighbours.");
                            neighbours.InformOurRegionsOfNewNeighbor(regionInfo);
                        }
                    }
                }
            }

            //  Either generate the terrain or loading from an existing file, DEM for example.
            m_log.Info("[CITY BUILDER]: [TERRAIN]");

            //  Construct the new terrain for each region and pass the height map to it.
            //  For the entire area covered by all of the regions construct a new terrain heightfield for it.
            // Also construct several maps that can be blended together in order to provide a suitablly natural
            // looking terrain which is not too flat or doesn't entirely consist of mountains.
            float[,] terrainMap;
            float[,] hMap1;
            float[,] hMap2;
            float[,] hMap3;
            float[,] hMap4;
            float[] bFactors = new float[4];
            int size = regionInfo.RegionSizeX;
            int y;
            int x;

            terrainMap = new float[ size * r, size * r ];
            hMap1 = new float[ size * r, size * r ];
            hMap2 = new float[ size * r, size * r ];
            hMap3 = new float[ size * r, size * r ];
            hMap4 = new float[ size * r, size * r ];
            //  Set blending factors.
            bFactors[0] = 0.75f;
            bFactors[1] = 0.55f;
            bFactors[2] = 0.35f;
            bFactors[3] = 0.05f;

            //  Generate four layers for the initial height map and then blend them together.
            for (x = 0; x < size; x++)
            {
                for (y = 0; y < size; y++)
                {
                    for (int i = 0; i < r; i++)
                    {
                        for (int j = 0; j < r; j++)
                        {
                            hMap1[i * x, i * y] = Perlin.noise2((float)x+i, (float)y+i);
                            hMap2[i * x, i * y] = Perlin.noise2((float)x, (float)y+i);
                            hMap3[i * x, i * y] = Perlin.noise2((float)x+i, (float)y);
                            hMap4[i * x, i * y] = Perlin.noise2((float)x+j, (float)y+i);
                            terrainMap[i*x, i*y] = (hMap1[i*x, i*y] * bFactors[0]) + (hMap2[i*x, i*y] * bFactors[1]) +
                                (hMap3[i*x, i*y] * bFactors[2]) + (hMap4[i*x, i*y] * bFactors[3]);
                        }
                    }
                }
            }

            //  DEBUG code that will save the resulting terrainMap as a jpeg image.
            m_log.Info("[CITY BUILDER]: Debug, save terrain map (full) as a jpeg image.");
            ManagedImage mImage = new ManagedImage(r * size, r * size, ManagedImage.ImageChannels.Bump);

            //   Find a way of copying the terrainMap array into the newly created image, then save
            // the image to disk.

            m_log.Info("[CITY BUILDER]: Terrain built and blended, tiling and region application.");

            //  Set the height map of each region based on the newly created terrainMap.
            ITerrain terrain = null;
            for (rx = 0; rx < r; rx++)
            {
                for (ry = 0; ry < r; ry++)
                {
                    Scene region = cityMap.cityRegions[rx, ry];
                    ITerrainChannel tChannel = new TerrainChannel(true, region);
                    region.TryRequestModuleInterface<ITerrain>(out terrain);

                    m_log.InfoFormat("[CITY BUILDER]: Region [ {0}, {1} ]", rx, ry);

                    float[,] tile = new float[ size, size ];
                    for (int i = 0; i < size; i++)
                    {
                        for (int j = 0; i < size; j++)
                        {
                            tile[i, j] = terrainMap[(rx * size) + i, (ry * size) + j];
                        }
                    }

                    if (terrain != null & tile!=null)
                        terrain.SetHeights2D(tile);

                    // dispose of the tile now thats its not needed as a new tile is allocated next loop run.
                    tile = null;
                }
            }

            //  Rivers and other waterways. Randomly select a number of rivers for the entire area
            // and place them.
            int rCount = CityModule.randomValue(size / r);
            m_log.InfoFormat("[CITY BUILDER]: River count for entire area {0}", rCount);

            //  From the total number of regions pick a number of regions that will be 'centers'
            // for the entire city, record these in the centralRegions list.
            m_log.Info("[CITY BUILDER]: [CENTERS]");
            //  ( region count * region count ) / 3
            int aNum = CityModule.randomValue((cityMap.cityRegions.GetUpperBound(0) * cityMap.cityRegions.GetUpperBound(1))/3);
            if (aNum == 0)
            {
                aNum = 1;
            }
            m_log.InfoFormat("[CITY BUILDER]: Total regions {0}, selecting {1} regions for centers.", (r*r), aNum );
            int prevRegionX = 0;
            int prevRegionY = 0;
            while ( aNum > 0 )
            {
                int currRegionX = randomValue( cityMap.cityRegions.GetUpperBound(0) ) / 2;
                int currRegionY = randomValue( cityMap.cityRegions.GetUpperBound(1) ) / 2;

                // If the location selected is the same as the previous location try again.
                if (currRegionX == prevRegionX && currRegionY == prevRegionY)
                {
                    aNum--;
                    continue;
                }

                m_log.InfoFormat("[CITY BUILDER]: Region {0}, located {1},{2}", aNum, prevRegionX, prevRegionY);

                try
                {
                    Scene region = cityMap.centralRegions[(prevRegionX * cityMap.cityRegions.GetUpperBound(0)) + prevRegionY];
                    if (region!=null)
                    {
                        cityMap.centralRegions.Add(region);
                    }
                }
                catch
                {
                }
                aNum--;
                prevRegionX = currRegionX;
                prevRegionY = currRegionY;
            }

            m_log.Info("[CITY BUILDER]: [DENSITY]");
            float avgDensity = 0.0f;

            avgDensity += cityDensities[0];
            avgDensity += cityDensities[1];
            avgDensity += cityDensities[2];
            avgDensity += cityDensities[3];
            avgDensity /= 4;

            //  Before ANYTHING else is created construct the transport systems, priority is given
            // to the road network before the rail network, perhaps a configuration option to allow
            // for the prioritisation value of the transport system is possible.
            m_log.Info("[CITY BUILDER]: [FREEWAYS]");

            //  Construct a road system (high speed ~50-70 mph) between and around the city center regions.

            m_log.Info("[CITY BUILDER]: [HIGHWAYS]");

            m_log.Info("[CITY BUILDER]: [STREETS]");

            m_log.Info("[CITY BUILDER]: [RAILWAYS]");

            m_log.InfoFormat("[CITY BUILDER]: [RESIDENTIAL DENSITY] {0}%", cityDensities[0] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [COMMERCIAL DENSITY] {0}%", cityDensities[1] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [CORPORATE DENSITY] {0}%", cityDensities[2] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [INDUSTRIAL DENISTY] {0}%", cityDensities[3] * 100);
            m_log.InfoFormat("[CITY BUILDER]: [AVERAGE DENSITY] {0}%", avgDensity);

            m_log.Info("[CITY BUILDER]: [BLOCKS]");
            m_log.Info("[CITY BUILDER]: [ALLOTMENT PLOTS]");
            m_log.Info("[CITY BUILDER]: [BUILDINGS]");

            return (true);
        }
Esempio n. 7
0
        private void MultiplyLayerFromAlpha(ManagedImage dest, ManagedImage src)
        {
            if (!SanitizeLayers(dest, src)) return;

            for (int i = 0; i < dest.Red.Length; i++)
            {
                dest.Red[i] = (byte)((dest.Red[i] * src.Alpha[i]) >> 8);
                dest.Green[i] = (byte)((dest.Green[i] * src.Alpha[i]) >> 8);
                dest.Blue[i] = (byte)((dest.Blue[i] * src.Alpha[i]) >> 8);
            }
        }
Esempio n. 8
0
        private void ApplyTint(ManagedImage dest, Color4 src)
        {
            if (dest == null) return;

            for (int i = 0; i < dest.Red.Length; i++)
            {
                dest.Red[i] = (byte)((dest.Red[i] * ((byte)(src.R * byte.MaxValue))) >> 8);
                dest.Green[i] = (byte)((dest.Green[i] * ((byte)(src.G * byte.MaxValue))) >> 8);
                dest.Blue[i] = (byte)((dest.Blue[i] * ((byte)(src.B * byte.MaxValue))) >> 8);
            }
        }
Esempio n. 9
0
        private void AddAlpha(ManagedImage dest, ManagedImage src)
        {
            if (!SanitizeLayers(dest, src)) return;

            for (int i = 0; i < dest.Alpha.Length; i++)
            {
                if (src.Alpha[i] < dest.Alpha[i])
                {
                    dest.Alpha[i] = src.Alpha[i];
                }
            }
        }
Esempio n. 10
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="encoded"></param>
        /// <param name="managedImage"></param>
        /// <returns></returns>
        public static bool DecodeToImage(byte[] encoded, out ManagedImage managedImage)
        {
            MarshalledImage marshalled = new MarshalledImage();

            // Allocate and copy to input buffer
            marshalled.length = encoded.Length;

            lock (OpenJPEGLock)
            {
                DotNetAllocEncoded(ref marshalled);
                Marshal.Copy(encoded, 0, marshalled.encoded, encoded.Length);

                // Codec will allocate output buffer
                DotNetDecode(ref marshalled);

                int n = marshalled.width * marshalled.height;

                switch (marshalled.components)
                {
                    case 1: // Grayscale
                        managedImage = new ManagedImage(marshalled.width, marshalled.height,
                            ManagedImage.ImageChannels.Color);
                        Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n);
                        Buffer.BlockCopy(managedImage.Red, 0, managedImage.Green, 0, n);
                        Buffer.BlockCopy(managedImage.Red, 0, managedImage.Blue, 0, n);
                        break;

                    case 2: // Grayscale + alpha
                        managedImage = new ManagedImage(marshalled.width, marshalled.height,
                            ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha);
                        Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n);
                        Buffer.BlockCopy(managedImage.Red, 0, managedImage.Green, 0, n);
                        Buffer.BlockCopy(managedImage.Red, 0, managedImage.Blue, 0, n);
                        Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)n), managedImage.Alpha, 0, n);
                        break;

                    case 3: // RGB
                        managedImage = new ManagedImage(marshalled.width, marshalled.height,
                            ManagedImage.ImageChannels.Color);
                        Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n);
                        Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)n), managedImage.Green, 0, n);
                        Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 2)), managedImage.Blue, 0, n);
                        break;

                    case 4: // RGBA
                        managedImage = new ManagedImage(marshalled.width, marshalled.height,
                            ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha);
                        Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n);
                        Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)n), managedImage.Green, 0, n);
                        Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 2)), managedImage.Blue, 0, n);
                        Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 3)), managedImage.Alpha, 0, n);
                        break;

                    case 5: // RGBBA
                        managedImage = new ManagedImage(marshalled.width, marshalled.height,
                            ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha | ManagedImage.ImageChannels.Bump);
                        Marshal.Copy(marshalled.decoded, managedImage.Red, 0, n);
                        Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)n), managedImage.Green, 0, n);
                        Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 2)), managedImage.Blue, 0, n);
                        // Bump comes before alpha in 5 channel encode
                        Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 3)), managedImage.Bump, 0, n);
                        Marshal.Copy((IntPtr)(marshalled.decoded.ToInt64() + (long)(n * 4)), managedImage.Alpha, 0, n);
                        break;

                    default:
                        Logger.Log("Decoded image with unhandled number of components: " + marshalled.components,
                            Helpers.LogLevel.Error);
                        DotNetFree(ref marshalled);
                        managedImage = null;
                        return false;
                }

                DotNetFree(ref marshalled);
            }

            return true;
        }
Esempio n. 11
0
        /// <summary>
        /// Decode JPEG2000 data to an <seealso cref="System.Drawing.Image"/> and
        /// <seealso cref="ManagedImage"/>
        /// </summary>
        /// <param name="encoded">JPEG2000 encoded data</param>
        /// <param name="managedImage">ManagedImage object to decode to</param>
        /// <param name="image">Image object to decode to</param>
        /// <returns>True if the decode succeeds, otherwise false</returns>
        public static bool DecodeToImage(byte[] encoded, out ManagedImage managedImage, out Image image)
        {
            managedImage = null;
            image = null;

            if (DecodeToImage(encoded, out managedImage))
            {
                try
                {
                    image = LoadTGAClass.LoadTGA(new MemoryStream(managedImage.ExportTGA()));
                    return true;
                }
                catch (Exception ex)
                {
                    Logger.Log("Failed to export and load TGA data from decoded image", Helpers.LogLevel.Error, ex);
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
Esempio n. 12
0
 /// <summary>
 /// Encode a <seealso cref="ManagedImage"/> object into a byte array
 /// </summary>
 /// <param name="image">The <seealso cref="ManagedImage"/> object to encode</param>
 /// <returns>a byte array of the encoded image</returns>
 public static byte[] Encode(ManagedImage image)
 {
     return Encode(image, false);
 }
Esempio n. 13
0
        /// <summary>
        /// Encode a <seealso cref="ManagedImage"/> object into a byte array
        /// </summary>
        /// <param name="image">The <seealso cref="ManagedImage"/> object to encode</param>
        /// <param name="lossless">true to enable lossless conversion, only useful for small images ie: sculptmaps</param>
        /// <returns>A byte array containing the encoded Image object</returns>
        public static byte[] Encode(ManagedImage image, bool lossless)
        {
            if ((image.Channels & ManagedImage.ImageChannels.Color) == 0 ||
                ((image.Channels & ManagedImage.ImageChannels.Bump) != 0 && (image.Channels & ManagedImage.ImageChannels.Alpha) == 0))
                throw new ArgumentException("JPEG2000 encoding is not supported for this channel combination");

            byte[] encoded = null;
            MarshalledImage marshalled = new MarshalledImage();

            // allocate and copy to input buffer
            marshalled.width = image.Width;
            marshalled.height = image.Height;
            marshalled.components = 3;
            if ((image.Channels & ManagedImage.ImageChannels.Alpha) != 0) marshalled.components++;
            if ((image.Channels & ManagedImage.ImageChannels.Bump) != 0) marshalled.components++;

            lock (OpenJPEGLock)
            {
                if (!DotNetAllocDecoded(ref marshalled))
                    throw new Exception("DotNetAllocDecoded failed");

                int n = image.Width * image.Height;

                if ((image.Channels & ManagedImage.ImageChannels.Color) != 0)
                {
                    Marshal.Copy(image.Red, 0, marshalled.decoded, n);
                    Marshal.Copy(image.Green, 0, (IntPtr)(marshalled.decoded.ToInt64() + n), n);
                    Marshal.Copy(image.Blue, 0, (IntPtr)(marshalled.decoded.ToInt64() + n * 2), n);
                }

                if ((image.Channels & ManagedImage.ImageChannels.Alpha) != 0) Marshal.Copy(image.Alpha, 0, (IntPtr)(marshalled.decoded.ToInt64() + n * 3), n);
                if ((image.Channels & ManagedImage.ImageChannels.Bump) != 0) Marshal.Copy(image.Bump, 0, (IntPtr)(marshalled.decoded.ToInt64() + n * 4), n);

                // codec will allocate output buffer
                if (!DotNetEncode(ref marshalled, lossless))
                    throw new Exception("DotNetEncode failed");

                // copy output buffer
                encoded = new byte[marshalled.length];
                Marshal.Copy(marshalled.encoded, encoded, 0, marshalled.length);

                // free buffers
                DotNetFree(ref marshalled);
            }

            return encoded;
        }
Esempio n. 14
0
 public AssetTexture(ManagedImage image)
 {
     Image = image;
 }
Esempio n. 15
0
 public static ManagedImage LoadResourceLayer(string fileName)
 {
     try
     {
         Bitmap bitmap = null;
         lock (ResourceSync)
         {
             using (Stream stream = Helpers.GetResourceStream(fileName, Settings.RESOURCE_DIR))
             {
                 bitmap = LoadTGAClass.LoadTGA(stream);
             }
         }
         if (bitmap == null)
         {
             Logger.Log(String.Format("Failed loading resource file: {0}", fileName), Helpers.LogLevel.Error);
             return null;
         }
         else
         {
             ManagedImage image = new ManagedImage(bitmap);
             bitmap.Dispose();
             return image;
         }
     }
     catch (Exception e)
     {
         Logger.Log(String.Format("Failed loading resource file: {0} ({1})", fileName, e.Message),
             Helpers.LogLevel.Error, e);
         return null;
     }
 }
Esempio n. 16
0
        /// <summary>
        /// Encode a <seealso cref="System.Drawing.Bitmap"/> object into a byte array
        /// </summary>
        /// <param name="bitmap">The source <seealso cref="System.Drawing.Bitmap"/> object to encode</param>
        /// <param name="lossless">true to enable lossless decoding</param>
        /// <returns>A byte array containing the source Bitmap object</returns>
        public unsafe static byte[] EncodeFromImage(Bitmap bitmap, bool lossless)
        {
            BitmapData bd;
            ManagedImage decoded;

            int bitmapWidth = bitmap.Width;
            int bitmapHeight = bitmap.Height;
            int pixelCount = bitmapWidth * bitmapHeight;
            int i;

            if ((bitmap.PixelFormat & PixelFormat.Alpha) != 0 || (bitmap.PixelFormat & PixelFormat.PAlpha) != 0)
            {
                // Four layers, RGBA
                decoded = new ManagedImage(bitmapWidth, bitmapHeight,
                    ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha);
                bd = bitmap.LockBits(new Rectangle(0, 0, bitmapWidth, bitmapHeight),
                    ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
                byte* pixel = (byte*)bd.Scan0;

                for (i = 0; i < pixelCount; i++)
                {
                    // GDI+ gives us BGRA and we need to turn that in to RGBA
                    decoded.Blue[i] = *(pixel++);
                    decoded.Green[i] = *(pixel++);
                    decoded.Red[i] = *(pixel++);
                    decoded.Alpha[i] = *(pixel++);
                }
            }
            else if (bitmap.PixelFormat == PixelFormat.Format16bppGrayScale)
            {
                // One layer
                decoded = new ManagedImage(bitmapWidth, bitmapHeight,
                    ManagedImage.ImageChannels.Color);
                bd = bitmap.LockBits(new Rectangle(0, 0, bitmapWidth, bitmapHeight),
                    ImageLockMode.ReadOnly, PixelFormat.Format16bppGrayScale);
                byte* pixel = (byte*)bd.Scan0;

                for (i = 0; i < pixelCount; i++)
                {
                    // Normalize 16-bit data down to 8-bit
                    ushort origVal = (byte)(*(pixel) + (*(pixel + 1) << 8));
                    byte val = (byte)(((double)origVal / (double)UInt32.MaxValue) * (double)Byte.MaxValue);

                    decoded.Red[i] = val;
                    decoded.Green[i] = val;
                    decoded.Blue[i] = val;
                    pixel += 2;
                }
            }
            else
            {
                // Three layers, RGB
                decoded = new ManagedImage(bitmapWidth, bitmapHeight,
                    ManagedImage.ImageChannels.Color);
                bd = bitmap.LockBits(new Rectangle(0, 0, bitmapWidth, bitmapHeight),
                    ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
                byte* pixel = (byte*)bd.Scan0;

                for (i = 0; i < pixelCount; i++)
                {
                    decoded.Blue[i] = *(pixel++);
                    decoded.Green[i] = *(pixel++);
                    decoded.Red[i] = *(pixel++);
                }
            }

            bitmap.UnlockBits(bd);
            byte[] encoded = Encode(decoded, lossless);
            return encoded;
        }
Esempio n. 17
0
        public void Bake()
        {
            bakedTexture = new AssetTexture(new ManagedImage(bakeWidth, bakeHeight,
                ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha | ManagedImage.ImageChannels.Bump));

            // Base color for eye bake is white, color of layer0 for others
            if (bakeType == BakeType.Eyes)
            {
                InitBakedLayerColor(Color4.White);
            }
            else if (textures.Count > 0)
            {
                InitBakedLayerColor(textures[0].Color);
            }

            // Do we have skin texture?
            bool SkinTexture = textures.Count > 0 && textures[0].Texture != null;

            if (bakeType == BakeType.Head)
            {
                DrawLayer(LoadResourceLayer("head_color.tga"), false);
                AddAlpha(bakedTexture.Image, LoadResourceLayer("head_alpha.tga"));
                MultiplyLayerFromAlpha(bakedTexture.Image, LoadResourceLayer("head_skingrain.tga"));
            }

            if (!SkinTexture && bakeType == BakeType.UpperBody)
            {
                DrawLayer(LoadResourceLayer("upperbody_color.tga"), false);
            }

            if (!SkinTexture && bakeType == BakeType.LowerBody)
            {
                DrawLayer(LoadResourceLayer("lowerbody_color.tga"), false);
            }

            ManagedImage alphaWearableTexture = null;

            // Layer each texture on top of one other, applying alpha masks as we go
            for (int i = 0; i < textures.Count; i++)
            {
                // Skip if we have no texture on this layer
                if (textures[i].Texture == null) continue;

                // Is this Alpha wearable and does it have an alpha channel?
                if (textures[i].TextureIndex >= AvatarTextureIndex.LowerAlpha &&
                    textures[i].TextureIndex <= AvatarTextureIndex.HairAlpha)
                {
                    if (textures[i].Texture.Image.Alpha != null)
                    {
                        alphaWearableTexture = textures[i].Texture.Image.Clone();
                    }
                    continue;
                }

                // Don't draw skin and tattoo on head bake first
                // For head bake the skin and texture are drawn last, go figure
                if (bakeType == BakeType.Head && (i == 0 || i == 1)) continue;

                ManagedImage texture = textures[i].Texture.Image.Clone();
                //File.WriteAllBytes(bakeType + "-texture-layer-" + i + ".tga", texture.ExportTGA());

                // Resize texture to the size of baked layer
                // FIXME: if texture is smaller than the layer, don't stretch it, tile it
                if (texture.Width != bakeWidth || texture.Height != bakeHeight)
                {
                    try { texture.ResizeNearestNeighbor(bakeWidth, bakeHeight); }
                    catch (Exception) { continue; }
                }

                // Special case for hair layer for the head bake
                // If we don't have skin texture, we discard hair alpha
                // and apply hair(i==2) pattern over the texture
                if (!SkinTexture && bakeType == BakeType.Head && i == 2)
                {
                    if (texture.Alpha != null)
                    {
                        for (int j = 0; j < texture.Alpha.Length; j++) texture.Alpha[j] = (byte)255;
                    }
                    MultiplyLayerFromAlpha(texture, LoadResourceLayer("head_hair.tga"));
                }

                // Aply tint and alpha masks except for skin that has a texture
                // on layer 0 which always overrides other skin settings
                if (!(IsSkin && i == 0))
                {
                    ApplyTint(texture, textures[i].Color);

                    // For hair bake, we skip all alpha masks
                    // and use one from the texture, for both
                    // alpha and morph layers
                    if (bakeType == BakeType.Hair)
                    {
                        if (texture.Alpha != null)
                        {
                            bakedTexture.Image.Bump = texture.Alpha;
                        }
                        else
                        {
                            for (int j = 0; j < bakedTexture.Image.Bump.Length; j++) bakedTexture.Image.Bump[j] = byte.MaxValue;
                        }
                    }
                    // Apply parametrized alpha masks
                    else if (textures[i].AlphaMasks != null && textures[i].AlphaMasks.Count > 0)
                    {
                        // Combined mask for the layer, fully transparent to begin with
                        ManagedImage combinedMask = new ManagedImage(bakeWidth, bakeHeight, ManagedImage.ImageChannels.Alpha);

                        int addedMasks = 0;

                        // First add mask in normal blend mode
                        foreach (KeyValuePair<VisualAlphaParam, float> kvp in textures[i].AlphaMasks)
                        {
                            if (!MaskBelongsToBake(kvp.Key.TGAFile)) continue;

                            if (kvp.Key.MultiplyBlend == false && (kvp.Value > 0f || !kvp.Key.SkipIfZero))
                            {
                                ApplyAlpha(combinedMask, kvp.Key, kvp.Value);
                                //File.WriteAllBytes(bakeType + "-layer-" + i + "-mask-" + addedMasks + ".tga", combinedMask.ExportTGA());
                                addedMasks++;
                            }
                        }

                        // If there were no mask in normal blend mode make aplha fully opaque
                        if (addedMasks == 0) for (int l = 0; l < combinedMask.Alpha.Length; l++) combinedMask.Alpha[l] = 255;

                        // Add masks in multiply blend mode
                        foreach (KeyValuePair<VisualAlphaParam, float> kvp in textures[i].AlphaMasks)
                        {
                            if (!MaskBelongsToBake(kvp.Key.TGAFile)) continue;

                            if (kvp.Key.MultiplyBlend == true && (kvp.Value > 0f || !kvp.Key.SkipIfZero))
                            {
                                ApplyAlpha(combinedMask, kvp.Key, kvp.Value);
                                //File.WriteAllBytes(bakeType + "-layer-" + i + "-mask-" + addedMasks + ".tga", combinedMask.ExportTGA());
                                addedMasks++;
                            }
                        }

                        if (addedMasks > 0)
                        {
                            // Apply combined alpha mask to the cloned texture
                            AddAlpha(texture, combinedMask);
                        }

                        // Is this layer used for morph mask? If it is, use its
                        // alpha as the morth for the whole bake
                        if (Textures[i].TextureIndex == AppearanceManager.MorphLayerForBakeType(bakeType))
                        {
                            bakedTexture.Image.Bump = texture.Alpha;
                        }

                        //File.WriteAllBytes(bakeType + "-masked-texture-" + i + ".tga", texture.ExportTGA());
                    }
                }

                bool useAlpha = i == 0 && (BakeType == BakeType.Skirt || BakeType == BakeType.Hair);
                DrawLayer(texture, useAlpha);
                //File.WriteAllBytes(bakeType + "-layer-" + i + ".tga", texture.ExportTGA());
            }

            // For head and tattoo, we add skin last
            if (IsSkin && bakeType == BakeType.Head)
            {
                ManagedImage texture;
                if (textures[0].Texture != null)
                {
                    texture = textures[0].Texture.Image.Clone();
                    if (texture.Width != bakeWidth || texture.Height != bakeHeight)
                    {
                        try { texture.ResizeNearestNeighbor(bakeWidth, bakeHeight); }
                        catch (Exception) { }
                    }
                    DrawLayer(texture, false);
                }

                // Add head tattoo here (if available, order-dependant)
                if (textures.Count > 1 && textures[1].Texture != null)
                {
                    texture = textures[1].Texture.Image.Clone();
                    if (texture.Width != bakeWidth || texture.Height != bakeHeight)
                    {
                        try { texture.ResizeNearestNeighbor(bakeWidth, bakeHeight); }
                        catch (Exception) { }
                    }
                    DrawLayer(texture, false);
                }
            }

            // Apply any alpha wearable textures to make parts of the avatar disappear
            if (alphaWearableTexture != null)
            {
                AddAlpha(bakedTexture.Image, alphaWearableTexture);
            }

            // We are done, encode asset for finalized bake
            bakedTexture.Encode();
            //File.WriteAllBytes(bakeType + ".tga", bakedTexture.Image.ExportTGA());
        }
Esempio n. 18
0
        private bool DrawLayer(ManagedImage source, bool useSourceAlpha)
        {
            bool sourceHasColor;
            bool sourceHasAlpha;
            bool sourceHasBump;
            int i = 0;

            sourceHasColor = ((source.Channels & ManagedImage.ImageChannels.Color) != 0 &&
                    source.Red != null && source.Green != null && source.Blue != null);
            sourceHasAlpha = ((source.Channels & ManagedImage.ImageChannels.Alpha) != 0 && source.Alpha != null);
            sourceHasBump = ((source.Channels & ManagedImage.ImageChannels.Bump) != 0 && source.Bump != null);

            useSourceAlpha = (useSourceAlpha && sourceHasAlpha);

            if (source.Width != _bakeWidth || source.Height != _bakeHeight)
            {
                try { source.ResizeNearestNeighbor(_bakeWidth, _bakeHeight); }
                catch { return false; }
            }

            int alpha = 255;
            //int alphaInv = 255 - alpha;
            int alphaInv = 256 - alpha;

            byte[] bakedRed = _bakedTexture.Image.Red;
            byte[] bakedGreen = _bakedTexture.Image.Green;
            byte[] bakedBlue = _bakedTexture.Image.Blue;
            byte[] bakedAlpha = _bakedTexture.Image.Alpha;
            byte[] bakedBump = _bakedTexture.Image.Bump;

            byte[] sourceRed = source.Red;
            byte[] sourceGreen = source.Green;
            byte[] sourceBlue = source.Blue;
            byte[] sourceAlpha = null;
            byte[] sourceBump = null;

            if (sourceHasAlpha)
                sourceAlpha = source.Alpha;

            if (sourceHasBump)
                sourceBump = source.Bump;

            for (int y = 0; y < _bakeHeight; y++)
            {
                for (int x = 0; x < _bakeWidth; x++)
                {
                    if (sourceHasAlpha)
                    {
                        alpha = sourceAlpha[i];
                        //alphaInv = 255 - alpha;
                        alphaInv = 256 - alpha;
                    }

                    if (sourceHasColor)
                    {
                        bakedRed[i] = (byte)((bakedRed[i] * alphaInv + sourceRed[i] * alpha) >> 8);
                        bakedGreen[i] = (byte)((bakedGreen[i] * alphaInv + sourceGreen[i] * alpha) >> 8);
                        bakedBlue[i] = (byte)((bakedBlue[i] * alphaInv + sourceBlue[i] * alpha) >> 8);
                    }

                    if (useSourceAlpha)
                        bakedAlpha[i] = sourceAlpha[i];

                    if (sourceHasBump)
                        bakedBump[i] = sourceBump[i];

                    ++i;
                }
            }

            return true;
        }
Esempio n. 19
0
        private void ApplyAlpha(ManagedImage dest, VisualAlphaParam param, float val)
        {
            ManagedImage src = LoadResourceLayer(param.TGAFile);

            if (dest == null || src == null || src.Alpha == null) return;

            if ((dest.Channels & ManagedImage.ImageChannels.Alpha) == 0)
            {
                dest.ConvertChannels(ManagedImage.ImageChannels.Alpha | dest.Channels);
            }

            if (dest.Width != src.Width || dest.Height != src.Height)
            {
                try { src.ResizeNearestNeighbor(dest.Width, dest.Height); }
                catch (Exception) { return; }
            }

            for (int i = 0; i < dest.Alpha.Length; i++)
            {
                byte alpha = src.Alpha[i] <= ((1 - val) * 255) ? (byte)0 : (byte)255;
                if (alpha != 255)
                {
                }
                if (param.MultiplyBlend)
                {
                    dest.Alpha[i] = (byte)((dest.Alpha[i] * alpha) >> 8);
                }
                else
                {
                    if (alpha > dest.Alpha[i])
                    {
                        dest.Alpha[i] = alpha;
                    }
                }
            }
        }
Esempio n. 20
0
        public static ManagedImage LoadAlphaLayer(string fileName)
        {
            Stream stream = Helpers.GetResourceStream(fileName);

            if (stream != null)
            {
                try
                {
                    // FIXME: It would save cycles and memory if we wrote a direct
                    // loader to ManagedImage for these files instead of using the
                    // TGA loader
                    Bitmap bitmap = LoadTGAClass.LoadTGA(stream);
                    stream.Close();

                    ManagedImage alphaLayer = new ManagedImage(bitmap);

                    // Disable all layers except the alpha layer
                    alphaLayer.Red = null;
                    alphaLayer.Green = null;
                    alphaLayer.Blue = null;
                    alphaLayer.Channels = ManagedImage.ImageChannels.Alpha;

                    return alphaLayer;
                }
                catch (Exception e)
                {
                    Logger.Log(String.Format("LoadAlphaLayer() failed on file: {0} ({1}", fileName, e.Message),
                        Helpers.LogLevel.Error, e);
                    return null;
                }
            }
            else
            {
                return null;
            }

            
        }
Esempio n. 21
0
        private bool DrawLayer(ManagedImage source, bool addSourceAlpha)
        {
            if (source == null) return false;

            bool sourceHasColor;
            bool sourceHasAlpha;
            bool sourceHasBump;
            int i = 0;

            sourceHasColor = ((source.Channels & ManagedImage.ImageChannels.Color) != 0 &&
                    source.Red != null && source.Green != null && source.Blue != null);
            sourceHasAlpha = ((source.Channels & ManagedImage.ImageChannels.Alpha) != 0 && source.Alpha != null);
            sourceHasBump = ((source.Channels & ManagedImage.ImageChannels.Bump) != 0 && source.Bump != null);

            addSourceAlpha = (addSourceAlpha && sourceHasAlpha);

            byte alpha = Byte.MaxValue;
            byte alphaInv = (byte)(Byte.MaxValue - alpha);

            byte[] bakedRed = bakedTexture.Image.Red;
            byte[] bakedGreen = bakedTexture.Image.Green;
            byte[] bakedBlue = bakedTexture.Image.Blue;
            byte[] bakedAlpha = bakedTexture.Image.Alpha;
            byte[] bakedBump = bakedTexture.Image.Bump;

            byte[] sourceRed = source.Red;
            byte[] sourceGreen = source.Green;
            byte[] sourceBlue = source.Blue;
            byte[] sourceAlpha = sourceHasAlpha ? source.Alpha : null;
            byte[] sourceBump = sourceHasBump ? source.Bump : null;

            for (int y = 0; y < bakeHeight; y++)
            {
                for (int x = 0; x < bakeWidth; x++)
                {
                    if (sourceHasAlpha)
                    {
                        alpha = sourceAlpha[i];
                        alphaInv = (byte)(Byte.MaxValue - alpha);
                    }

                    if (sourceHasColor)
                    {
                        bakedRed[i] = (byte)((bakedRed[i] * alphaInv + sourceRed[i] * alpha) >> 8);
                        bakedGreen[i] = (byte)((bakedGreen[i] * alphaInv + sourceGreen[i] * alpha) >> 8);
                        bakedBlue[i] = (byte)((bakedBlue[i] * alphaInv + sourceBlue[i] * alpha) >> 8);
                    }

                    if (addSourceAlpha)
                    {
                        if (sourceAlpha[i] < bakedAlpha[i])
                        {
                            bakedAlpha[i] = sourceAlpha[i];
                        }
                    }

                    if (sourceHasBump)
                        bakedBump[i] = sourceBump[i];

                    ++i;
                }
            }

            return true;
        }
Esempio n. 22
0
        public static unsafe ManagedImage LoadTGAImage(System.IO.Stream source, bool mask)
        {
            byte[] buffer = new byte[source.Length];
            source.Read(buffer, 0, buffer.Length);

            System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer);

            using (System.IO.BinaryReader br = new System.IO.BinaryReader(ms))
            {
                tgaHeader header = new tgaHeader();
                header.Read(br);

                if (header.ImageSpec.PixelDepth != 8 &&
                    header.ImageSpec.PixelDepth != 16 &&
                    header.ImageSpec.PixelDepth != 24 &&
                    header.ImageSpec.PixelDepth != 32)
                    throw new ArgumentException("Not a supported tga file.");

                if (header.ImageSpec.AlphaBits > 8)
                    throw new ArgumentException("Not a supported tga file.");

                if (header.ImageSpec.Width > 4096 ||
                    header.ImageSpec.Height > 4096)
                    throw new ArgumentException("Image too large.");

                byte[] decoded = new byte[header.ImageSpec.Width * header.ImageSpec.Height * 4];
                System.Drawing.Imaging.BitmapData bd = new System.Drawing.Imaging.BitmapData();

                fixed (byte* pdecoded = &decoded[0])
                {
                    bd.Width = header.ImageSpec.Width;
                    bd.Height = header.ImageSpec.Height;
                    bd.PixelFormat = System.Drawing.Imaging.PixelFormat.Format32bppPArgb;
                    bd.Stride = header.ImageSpec.Width * 4;
                    bd.Scan0 = (IntPtr)pdecoded;

                    switch (header.ImageSpec.PixelDepth)
                    {
                        case 8:
                            decodeStandard8(bd, header, br);
                            break;
                        case 16:
                            if (header.ImageSpec.AlphaBits > 0)
                                decodeSpecial16(bd, header, br);
                            else
                                decodeStandard16(bd, header, br);
                            break;
                        case 24:
                            if (header.ImageSpec.AlphaBits > 0)
                                decodeSpecial24(bd, header, br);
                            else
                                decodeStandard24(bd, header, br);
                            break;
                        case 32:
                            decodeStandard32(bd, header, br);
                            break;
                        default:
                            return null;
                    }
                }

                int n = header.ImageSpec.Width * header.ImageSpec.Height;
                ManagedImage image;

                if (mask && header.ImageSpec.AlphaBits == 0 && header.ImageSpec.PixelDepth == 8)
                {
                    image = new ManagedImage(header.ImageSpec.Width, header.ImageSpec.Height,
                        ManagedImage.ImageChannels.Alpha);
                    int p = 3;

                    for (int i = 0; i < n; i++)
                    {
                        image.Alpha[i] = decoded[p];
                        p += 4;
                    }
                }
                else
                {
                    image = new ManagedImage(header.ImageSpec.Width, header.ImageSpec.Height,
                        ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha);
                    int p = 0;

                    for (int i = 0; i < n; i++)
                    {
                        image.Blue[i] = decoded[p++];
                        image.Green[i] = decoded[p++];
                        image.Red[i] = decoded[p++];
                        image.Alpha[i] = decoded[p++];
                    }
                }

                br.Close();
                return image;
            }
        }
Esempio n. 23
0
        /// <summary>
        /// Make sure images exist, resize source if needed to match the destination
        /// </summary>
        /// <param name="dest">Destination image</param>
        /// <param name="src">Source image</param>
        /// <returns>Sanitization was succefull</returns>
        private bool SanitizeLayers(ManagedImage dest, ManagedImage src)
        {
            if (dest == null || src == null) return false;

            if ((dest.Channels & ManagedImage.ImageChannels.Alpha) == 0)
            {
                dest.ConvertChannels(dest.Channels | ManagedImage.ImageChannels.Alpha);
            }

            if (dest.Width != src.Width || dest.Height != src.Height)
            {
                try { src.ResizeNearestNeighbor(dest.Width, dest.Height); }
                catch (Exception) { return false; }
            }

            return true;
        }
Esempio n. 24
0
        public static unsafe ManagedImage LoadTGAImage(System.IO.Stream source, bool mask)
        {
            byte[] buffer = new byte[source.Length];
            source.Read(buffer, 0, buffer.Length);

            System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer);

            using (System.IO.BinaryReader br = new System.IO.BinaryReader(ms))
            {
                tgaHeader header = new tgaHeader();
                header.Read(br);

                if (header.ImageSpec.PixelDepth != 8 &&
                    header.ImageSpec.PixelDepth != 16 &&
                    header.ImageSpec.PixelDepth != 24 &&
                    header.ImageSpec.PixelDepth != 32)
                {
                    throw new ArgumentException("Not a supported tga file.");
                }

                if (header.ImageSpec.AlphaBits > 8)
                {
                    throw new ArgumentException("Not a supported tga file.");
                }

                if (header.ImageSpec.Width > 4096 ||
                    header.ImageSpec.Height > 4096)
                {
                    throw new ArgumentException("Image too large.");
                }

                byte[] decoded = new byte[header.ImageSpec.Width * header.ImageSpec.Height * 4];
                System.Drawing.Imaging.BitmapData bd = new System.Drawing.Imaging.BitmapData();

                fixed(byte *pdecoded = &decoded[0])
                {
                    bd.Width       = header.ImageSpec.Width;
                    bd.Height      = header.ImageSpec.Height;
                    bd.PixelFormat = System.Drawing.Imaging.PixelFormat.Format32bppPArgb;
                    bd.Stride      = header.ImageSpec.Width * 4;
                    bd.Scan0       = (IntPtr)pdecoded;

                    switch (header.ImageSpec.PixelDepth)
                    {
                    case 8:
                        decodeStandard8(bd, header, br);
                        break;

                    case 16:
                        if (header.ImageSpec.AlphaBits > 0)
                        {
                            decodeSpecial16(bd, header, br);
                        }
                        else
                        {
                            decodeStandard16(bd, header, br);
                        }
                        break;

                    case 24:
                        if (header.ImageSpec.AlphaBits > 0)
                        {
                            decodeSpecial24(bd, header, br);
                        }
                        else
                        {
                            decodeStandard24(bd, header, br);
                        }
                        break;

                    case 32:
                        decodeStandard32(bd, header, br);
                        break;

                    default:
                        return(null);
                    }
                }

                int          n = header.ImageSpec.Width * header.ImageSpec.Height;
                ManagedImage image;

                if (mask && header.ImageSpec.AlphaBits == 0 && header.ImageSpec.PixelDepth == 8)
                {
                    image = new ManagedImage(header.ImageSpec.Width, header.ImageSpec.Height,
                                             ManagedImage.ImageChannels.Alpha);
                    int p = 3;

                    for (int i = 0; i < n; i++)
                    {
                        image.Alpha[i] = decoded[p];
                        p += 4;
                    }
                }
                else
                {
                    image = new ManagedImage(header.ImageSpec.Width, header.ImageSpec.Height,
                                             ManagedImage.ImageChannels.Color | ManagedImage.ImageChannels.Alpha);
                    int p = 0;

                    for (int i = 0; i < n; i++)
                    {
                        image.Blue[i]  = decoded[p++];
                        image.Green[i] = decoded[p++];
                        image.Red[i]   = decoded[p++];
                        image.Alpha[i] = decoded[p++];
                    }
                }

                br.Close();
                return(image);
            }
        }