Пример #1
0
        public void TestEquals()
        {
            TexImage image2 = new TexImage(new IntPtr(), 699104, 512, 512, 1, SiliconStudio.Paradox.Graphics.PixelFormat.BC3_UNorm, 10, 2, TexImage.TextureDimension.Texture2D);
            Assert.IsTrue(image.Equals(image2));

            image2 = new TexImage(new IntPtr(), 699104, 512, 256, 1, SiliconStudio.Paradox.Graphics.PixelFormat.BC3_UNorm, 10, 2, TexImage.TextureDimension.Texture2D);
            Assert.IsFalse(image.Equals(image2));
        }
Пример #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TexAtlas"/> class.
 /// </summary>
 /// <param name="layout">The layout.</param>
 /// <param name="atlas">The atlas.</param>
 public TexAtlas(TexLayout layout, TexImage atlas)
     : base(atlas.Data, atlas.DataSize, atlas.Width, atlas.Height, atlas.Depth, atlas.Format, atlas.MipmapCount, atlas.ArraySize, atlas.Dimension, atlas.FaceCount)
 {
     RowPitch = atlas.RowPitch;
     SlicePitch = atlas.SlicePitch;
     SubImageArray = atlas.SubImageArray;
     Name = atlas.Name;
     DisposingLibrary = atlas.DisposingLibrary;
     CurrentLibrary = atlas.CurrentLibrary;
     LibraryData = atlas.LibraryData;
     Layout = layout;
     Name = "";
 }
Пример #3
0
        private void HandleResizing(TextureTool texTool, TexImage image)
        {
            if (Width != null && Height != null)
            {
                bool targetInPercent;
                var  width  = ParsePixelSize(Width, out targetInPercent);
                var  height = ParsePixelSize(Height, out targetInPercent);

                if (targetInPercent)
                {
                    texTool.Rescale(image, width / 100f, height / 100f, RescalingFilter);
                }
                else
                {
                    texTool.Resize(image, width, height, RescalingFilter);
                }
            }
            else if (Width != null && Height == null)
            {
                bool targetInPercent;
                var  width = ParsePixelSize(Width, out targetInPercent);

                if (targetInPercent)
                {
                    texTool.Rescale(image, width / 100f, 1, RescalingFilter);
                }
                else
                {
                    texTool.Resize(image, width, image.Height, RescalingFilter);
                }
            }
            else if (Width == null && Height != null)
            {
                bool targetInPercent;
                var  height = ParsePixelSize(Height, out targetInPercent);

                if (targetInPercent)
                {
                    texTool.Rescale(image, 1, height / 100f, RescalingFilter);
                }
                else
                {
                    texTool.Resize(image, image.Width, height, RescalingFilter);
                }
            }
        }
Пример #4
0
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return(false);
            }
            if (ReferenceEquals(this, obj))
            {
                return(true);
            }
            if (obj.GetType() != this.GetType())
            {
                return(false);
            }

            TexImage img = (TexImage)obj;

            if (SubImageArray.Length != img.SubImageArray.Length)
            {
                return(false);
            }
            for (int i = 0; i < SubImageArray.Length; ++i)
            {
                if (!(SubImageArray[i].DataSize == img.SubImageArray[i].DataSize &&
                      SubImageArray[i].Width == img.SubImageArray[i].Width &&
                      SubImageArray[i].Height == img.SubImageArray[i].Height &&
                      SubImageArray[i].RowPitch == img.SubImageArray[i].RowPitch &&
                      SubImageArray[i].SlicePitch == img.SubImageArray[i].SlicePitch))
                {
                    return(false);
                }
            }

            return(Width == img.Width &&
                   Height == img.Height &&
                   Depth == img.Depth &&
                   Format == img.Format &&
                   MipmapCount == img.MipmapCount &&
                   ArraySize == img.ArraySize &&
                   FaceCount == img.FaceCount &&
                   Dimension == img.Dimension &&
                   DataSize == img.DataSize &&
                   RowPitch == img.RowPitch &&
                   SlicePitch == img.SlicePitch);
        }
Пример #5
0
        /// <summary>
        /// Removes the texture at a specified position from a texture array.
        /// </summary>
        /// <param name="array">The array.</param>
        /// <param name="indice">The indice.</param>
        /// <exception cref="TextureToolsException">
        /// The array size must be > 1.
        /// or
        /// The given indice must be between 0 and  + array.ArraySize
        /// </exception>
        public void Remove(TexImage array, int indice)
        {
            if (array.ArraySize == 1)
            {
                Log.Error("The array size must be > 1.");
                throw new TextureToolsException("The array size must be > 1.");
            }

            if (indice < 0 || indice > array.ArraySize-1)
            {
                Log.Error("The given indice must be between 0 and " + array.ArraySize);
                throw new TextureToolsException("The given indice must be between 0 and " + array.ArraySize);
            }

            ExecuteRequest(array, new ArrayElementRemovalRequest(indice));
        }
Пример #6
0
        /// <summary>
        /// Converts to paradox image.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <returns>The converted Paradox <see cref="SiliconStudio.Paradox.Graphics.Image"/>.</returns>
        /// <remarks>The user is the owner of the returned image, and has to dispose it after he finishes using it</remarks>
        public SiliconStudio.Paradox.Graphics.Image ConvertToParadoxImage(TexImage image)
        {
            var request = new ExportToParadoxRequest();

            ExecuteRequest(image, request);

            return request.PdxImage;
        }
Пример #7
0
        /// <summary>
        /// Flips the specified image horizontally or vertically.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="index">The index of the sub-image.</param>
        /// <param name="orientation">The orientation <see cref="Orientation.Flip"/>.</param>
        public void FlipSub(TexImage image, int index, Orientation orientation)
        {
            if (image.Format.IsCompressed())
            {
                Log.Warning("You can't flip a compressed texture. It will be decompressed first..");
                Decompress(image, image.Format.IsSRgb());
            }

            var request = new FlippingSubRequest(index, orientation);

            ExecuteRequest(image, request);
        }
Пример #8
0
        /// <summary>
        /// Create a new image from the alpha component of a reference image.
        /// </summary>
        /// <param name="texImage">The image from which to take the alpha</param>
        /// <returns>The <see cref="TexImage"/> containing the alpha component as rgb color. Note: it is the user responsibility to dispose the returned image.</returns>
        public unsafe TexImage CreateImageFromAlphaComponent(TexImage texImage)
        {
            if (texImage.Dimension != TexImage.TextureDimension.Texture2D || texImage.Format.IsCompressed())
                throw new NotImplementedException();

            var alphaImage = (TexImage)texImage.Clone(true);

            var rowPtr = alphaImage.Data;
            for (int i = 0; i < alphaImage.Height; i++)
            {
                var pByte = (byte*)rowPtr;
                for (int x = 0; x < alphaImage.Width; x++)
                {
                    pByte[0] = pByte[3];
                    pByte[1] = pByte[3];
                    pByte[2] = pByte[3];

                    pByte += 4;
                }
                rowPtr = IntPtr.Add(rowPtr, alphaImage.RowPitch);
            }

            return alphaImage;
        }
Пример #9
0
        /// <summary>
        /// Find the region of the texture containing the sprite under the specified pixel.
        /// </summary>
        /// <param name="texture">The texture containing the sprite</param>
        /// <param name="pixel">The coordinate of the pixel specifying the sprite</param>
        /// <param name="separatorColor">The separator color that delimit the sprites. If null the <see cref="Color.Transparent"/> color is used</param>
        /// <param name="separatorMask">The mask specifying which bits of the color should be checked. The bits are ordered as AABBGGRR.</param>
        /// <returns></returns>
        public unsafe Rectangle FindSpriteRegion(TexImage texture, Int2 pixel, Color? separatorColor = null, uint separatorMask = 0xff000000)
        {
            if (texture == null) throw new ArgumentNullException(nameof(texture));

            var format = texture.Format;
            if (texture.Dimension != TexImage.TextureDimension.Texture2D || !(format.IsRGBAOrder() || format.IsBGRAOrder() || format.SizeInBytes() != 4))
                throw new NotImplementedException();

            // adjust the separator color the mask depending on the color format.
            var separator = (uint)(separatorColor ?? Color.Transparent).ToRgba();
            if(texture.Format.IsBGRAOrder())
            {
                separator = RgbaToBgra(separator);
                separatorMask = RgbaToBgra(separatorMask);
            }
            var maskedSeparator = separator & separatorMask;
            
            var ptr = (uint*)texture.Data;
            var stride = texture.RowPitch / 4;

            // check for empty region (provided pixel is not valid)
            var textureRegion = new Rectangle(0, 0, texture.Width, texture.Height);
            if (!textureRegion.Contains(pixel) || (ptr[pixel.Y * stride + pixel.X] & separatorMask) == maskedSeparator)
                return new Rectangle(pixel.X, pixel.Y, 0, 0);

            // initialize the region with the provided pixel
            var region = new Rectangle(pixel.X, pixel.Y, 1, 1);

            var nextSearchOffsets = new[,]
            {
                { new Int2(-1, -1),  new Int2( 0, -1) },
                { new Int2( 1, -1),  new Int2( 1,  0) },
                { new Int2( 1,  1),  new Int2( 0,  1) },
                { new Int2(-1,  1),  new Int2(-1,  0) }
            };

            var contourLeftEgde = pixel;
            var rotationDirection = 0;
            do
            {
                // Stage 1: Find an edge of the shape (look to the left of the provided pixel as long as possible)
                var startEdge = contourLeftEgde;
                var startEdgeDirection = EdgeDirection.Left;
                for (int x = startEdge.X; x >= 0; --x)
                {
                    if ((ptr[startEdge.Y * stride + x] & separatorMask) == maskedSeparator)
                        break;

                    startEdge.X = x;
                }

                // Stage 2: Determine the whole contour of the shape and update the region. 
                // Note: the found contour can correspond to an internal hole contour or the external shape contour.
                var currentEdge = startEdge;
                var currentEdgeDirection = startEdgeDirection;
                do
                {
                    var previousEdgeDirection = currentEdgeDirection;

                    var diagonalPixel = currentEdge + nextSearchOffsets[(int)currentEdgeDirection, 0];
                    var diagonalIsSeparator = !textureRegion.Contains(diagonalPixel) || (ptr[diagonalPixel.Y * stride + diagonalPixel.X] & separatorMask) == maskedSeparator;
                    var neighbourPixel = currentEdge + nextSearchOffsets[(int)currentEdgeDirection, 1];
                    var neighbourIsSeparator = !textureRegion.Contains(neighbourPixel) || (ptr[neighbourPixel.Y * stride + neighbourPixel.X] & separatorMask) == maskedSeparator;

                    // determine the next edge position
                    if (!diagonalIsSeparator)
                    {
                        currentEdge = diagonalPixel;
                        currentEdgeDirection = (EdgeDirection)(((int)currentEdgeDirection + 3) % 4);
                    }
                    else if (!neighbourIsSeparator)
                    {
                        currentEdge = neighbourPixel;
                    }
                    else
                    {
                        currentEdgeDirection = (EdgeDirection)(((int)currentEdgeDirection + 1) % 4);
                    }

                    // keep record of the point of the edge which is 
                    if (currentEdge.X < contourLeftEgde.X)
                        contourLeftEgde = currentEdge;

                    // increase or decrease the rotation counter based on the sequence of edge direction
                    rotationDirection += RotationDirection(previousEdgeDirection, currentEdgeDirection);

                    // update the rectangle
                    region = Rectangle.Union(region, currentEdge);
                }
                while (currentEdge != startEdge || currentEdgeDirection != startEdgeDirection); // as long as we do not close the contour continue to explore
                
            } // repeat the process as long as the edge found is not the shape external contour.
            while (rotationDirection != 4);

            return region;
        }
Пример #10
0
        /// <summary>
        /// Resizes the specified image to a fixed image size.
        /// </summary>
        /// <remarks>
        /// If the image is in a compressed format, it will be first decompressed.
        /// </remarks>
        /// <param name="image">The image.</param>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        /// <param name="filter">The filter.</param>
        public void Resize(TexImage image, int width, int height, Filter.Rescaling filter)
        {
            if (width < 1 || height < 1)
            {
                Log.Error("The new size must be an integer > 0.");
                throw new TextureToolsException("The new size must be an integer > 0.");
            }

            // Texture already has the requested dimension
            if (image.Width == width && image.Height == height)
            {
                return;
            }

            if (image.Format.IsCompressed())
            {
                Log.Warning("You can't resize a compressed texture. It will be decompressed first..");
                Decompress(image, image.Format.IsSRgb());
            }

            ExecuteRequest(image, new FixedRescalingRequest(width, height, filter));
        }
Пример #11
0
        /// <summary>
        /// Generates the normal map.
        /// </summary>
        /// <param name="heightMap">The height map.</param>
        /// <param name="amplitude">The amplitude.</param>
        /// <returns>An instance of <see cref="TexImage"/> containig the normal map.</returns>
        public TexImage GenerateNormalMap(TexImage heightMap, float amplitude)
        {
            if (amplitude <= 0)
            {
                Log.Error("The amplitude must be a positive float.");
                throw new TextureToolsException("The amplitude must be a positive float.");
            }

            if (heightMap.Format.IsCompressed())
            {
                Log.Warning("You can't generate a normal map from a compressed height hmap. It will be decompressed first..");
                Decompress(heightMap, heightMap.Format.IsSRgb());
            }

            var request = new NormalMapGenerationRequest(amplitude);

            ExecuteRequest(heightMap, request);

            return request.NormalMap;
        }
Пример #12
0
        /// <summary>
        /// Switches the channel R and B.
        /// </summary>
        /// <remarks>
        /// PVR texture and ATC library can't handle BGRA order, channels B and R must be switched to get the new order RGBA. (This switch is made automatically)
        /// If the image is in a compressed format, it will be first decompressed.
        /// </remarks>
        /// <param name="image">The image.</param>
        public void SwitchChannel(TexImage image)
        {
            if (image.Format.IsCompressed())
            {
                Log.Warning("You can't switch channels of a compressed texture. It will be decompressed first..");
                Decompress(image, image.Format.IsSRgb());
            }

            ExecuteRequest(image, new SwitchingBRChannelsRequest());
        }
Пример #13
0
        /// <summary>
        /// Apply a color key on the image by replacing the color passed by to this method by a white transparent color (Alpha is 0).
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="colorKey">The color key.</param>
        public void ColorKey(TexImage image, Color colorKey)
        {
            if (image.Format.IsCompressed())
            {
                Log.Warning("You can't compress an already compressed texture. It will be decompressed first..");
                Decompress(image, image.Format.IsSRgb());
            }

            if (image.Format != PixelFormat.R8G8B8A8_UNorm && image.Format != PixelFormat.B8G8R8A8_UNorm 
                && image.Format != PixelFormat.B8G8R8A8_UNorm_SRgb && image.Format != PixelFormat.R8G8B8A8_UNorm_SRgb)
            {
                Log.Error("ColorKey TextureConverter is only supporting R8G8B8A8_UNorm or B8G8R8A8_UNorm while Texture Format is [{0}]", image.Format);
                return;
            }

            var request = new ColorKeyRequest(colorKey);
            ExecuteRequest(image, request);
        }
Пример #14
0
        /// <summary>
        /// Inserts a texture into a texture array at a specified position.
        /// </summary>
        /// <param name="array">The array.</param>
        /// <param name="texture">The texture to be added.</param>
        /// <param name="indice">The indice.</param>
        /// <exception cref="TextureToolsException">The given indice must be between 0 and the array size</exception>
        public void Insert(TexImage array, TexImage texture, int indice)
        {
            texture.Update();

            if (indice < 0 || indice > array.ArraySize)
            {
                Log.Error("The given indice must be between 0 and " + array.ArraySize);
                throw new TextureToolsException("The given indice must be between 0 and " + array.ArraySize);
            }

            CheckConformity(array, texture);

            ExecuteRequest(array, new ArrayInsertionRequest(texture, indice));
        }
Пример #15
0
        /// <summary>
        /// Retrieves the atlas from a TexImage and its corresponding layout file.
        /// </summary>
        /// <param name="texture">The texture.</param>
        /// <param name="layoutFile">The layout file.</param>
        /// <returns>An instance of <see cref="TexAtlas"/>.</returns>
        /// <exception cref="TextureToolsException">The layout file doesn't exist. Please check the file path.</exception>
        public TexAtlas RetrieveAtlas(TexImage texture, string layoutFile)
        {
            if (!File.Exists(layoutFile))
            {
                Log.Error("The file " + layoutFile + " doesn't exist. Please check the file path.");
                throw new TextureToolsException("The file " + layoutFile + " doesn't exist. Please check the file path.");
            }

            return new TexAtlas(TexAtlas.TexLayout.Import(layoutFile), texture);
        }
Пример #16
0
        /// <summary>
        /// Updates a specific texture in the texture array with the given TexImage.
        /// </summary>
        /// <param name="array">The array.</param>
        /// <param name="texture">The texture.</param>
        /// <param name="indice">The indice.</param>
        /// <exception cref="TextureToolsException">
        /// The first given texture must be an array texture.
        /// or
        /// The given indice is out of range in the array texture.
        /// </exception>
        public void Update(TexImage array, TexImage texture, int indice)
        {
            texture.Update();

            if (array.ArraySize == 1)
            {
                Log.Error("The first given texture must be an array texture.");
                throw new TextureToolsException("The first given texture must be an array texture.");
            }

            if (array.ArraySize-1 < indice)
            {
                Log.Error("The given indice is out of range in the array texture.");
                throw new TextureToolsException("The given indice is out of range in the array texture.");
            }

            CheckConformity(array, texture);

            ExecuteRequest(array, new ArrayUpdateRequest(texture, indice));
        }
Пример #17
0
        public void Run(string[] args)
        {
            // Print the exe header
            PrintHeader();

            foreach (String s in args)
            {
                Console.WriteLine(s);
            }

            Console.WriteLine("");

            // Parse the command line
            if (!ParseCommandLine(args))
            {
                Environment.Exit(-1);
            }

            // Check if we have a pattern
            InputPatternFile = Path.Combine(Environment.CurrentDirectory, InputPatternFile);

            int  indexOfPattern = InputPatternFile.IndexOf('*');
            bool isPattern      = indexOfPattern >= 0;

            if (!isPattern)
            {
                InputPatternFile = Path.GetFullPath(InputPatternFile);
            }
            OutputFileOrDirectory = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, OutputFileOrDirectory));

            var inputOutputFiles = new List <Tuple <string, string> >();

            if (isPattern)
            {
                if (!Directory.Exists(OutputFileOrDirectory))
                {
                    Directory.CreateDirectory(OutputFileOrDirectory);
                }

                var directory = InputPatternFile.Substring(0, indexOfPattern);
                var pattern   = InputPatternFile.Substring(indexOfPattern, InputPatternFile.Length - indexOfPattern);

                foreach (var file in Directory.EnumerateFiles(directory, pattern, SearchOption.AllDirectories))
                {
                    var outputFile = Path.Combine(OutputFileOrDirectory, file.Substring(directory.Length, file.Length - directory.Length));

                    bool excludeFile = false;
                    foreach (var excludeItem in ExcludeList)
                    {
                        if (file.IndexOf(excludeItem, StringComparison.InvariantCultureIgnoreCase) >= 0)
                        {
                            excludeFile = true;
                            break;
                        }
                    }

                    if (!excludeFile)
                    {
                        inputOutputFiles.Add(new Tuple <string, string>(file, outputFile));
                    }
                }
            }
            else
            {
                inputOutputFiles.Add(new Tuple <string, string>(InputPatternFile, OutputFileOrDirectory));
            }

            var texTool = new TextureTool();

            GlobalLogger.GlobalMessageLogged += new ConsoleLogListener();

            bool hasErrors = false;

            foreach (var inputOutputFile in inputOutputFiles)
            {
                var inputFile  = inputOutputFile.Item1;
                var outputFile = inputOutputFile.Item2;

                TexImage image = null;
                try
                {
                    image = texTool.Load(inputFile, IsSRgb);

                    HandleResizing(texTool, image);

                    if (FlipOrientation.HasValue)
                    {
                        texTool.Flip(image, FlipOrientation.Value);
                    }

                    if (MipMap)
                    {
                        texTool.GenerateMipMaps(image, MipMapFilter);
                    }

                    if (PreMulAlpha)
                    {
                        texTool.PreMultiplyAlpha(image);
                    }

                    if (TextureFormat.HasValue)
                    {
                        texTool.Compress(image, TextureFormat.Value);
                    }

                    texTool.Save(image, outputFile, MipMapSize);
                }
                catch (TextureToolsException)
                {
                    hasErrors = true;
                }
                finally
                {
                    if (image != null)
                    {
                        image.Dispose();
                    }
                }
            }

            texTool.Dispose();

            if (hasErrors)
            {
                //Environment.Exit(-1);
            }
        }
Пример #18
0
        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <param name="CopyMemory">if set to <c>true</c> [copy memory], it is a DEEP copy.</param>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        virtual public Object Clone(bool CopyMemory)
        {
            if (this.CurrentLibrary != null)
            {
                this.CurrentLibrary.EndLibrary(this); this.CurrentLibrary = null;
            }

            TexImage newTex = new TexImage()
            {
                // Basic infos
                Data               = CopyMemory?System.Runtime.InteropServices.Marshal.AllocHGlobal(this.DataSize):this.Data,
                DataSize           = this.DataSize,
                Width              = this.Width,
                Height             = this.Height,
                Depth              = this.Depth,
                RowPitch           = this.RowPitch,
                SlicePitch         = this.SlicePitch,
                Format             = this.Format,
                OriginalAlphaDepth = this.OriginalAlphaDepth,

                // Texture infos
                ArraySize     = this.ArraySize,
                FaceCount     = this.FaceCount,
                MipmapCount   = this.MipmapCount,
                SubImageArray = new SubImage[this.SubImageArray.Length],
                Dimension     = this.Dimension,
                Name          = this.Name,

                // ITexLibrary Data
                DisposingLibrary = this.DisposingLibrary,
                CurrentLibrary   = this.CurrentLibrary,
                LibraryData      = new Dictionary <ITexLibrary, ITextureLibraryData>(),

                // Disposing info
                Disposed = this.Disposed,
            };

            if (CopyMemory)
            {
                Utilities.CopyMemory(newTex.Data, this.Data, this.DataSize);
            }

            int offset = 0;

            for (int i = 0; i < this.SubImageArray.Length; ++i)
            {
                newTex.SubImageArray[i] = this.SubImageArray[i];
                if (CopyMemory)
                {
                    newTex.SubImageArray[i].Data = new IntPtr(newTex.Data.ToInt64() + offset);
                }
                offset += newTex.SubImageArray[i].DataSize;
            }

            if (CopyMemory && this.DisposingLibrary != null)
            {
                this.DisposingLibrary.StartLibrary(newTex);
            }
            else if (!CopyMemory)
            {
                newTex.DisposingLibrary = null;
            }

            return(newTex);
        }
Пример #19
0
        /// <summary>
        /// Compresses the specified image into the specified format.
        /// </summary>
        /// <remarks>
        /// If the image is in a compressed format, it will be first decompressed.
        /// If the compressing library doesn't support BGRA order and the current image format is in this order, the channels R and B will be switched.
        /// </remarks>
        /// <param name="image">The image.</param>
        /// <param name="format">The format.</param>
        public void Compress(TexImage image, PixelFormat format, TextureQuality quality = TextureQuality.Fast)
        {
            if (image.Format == format) return;

            if (image.Format.IsCompressed())
            {
                Log.Warning("You can't compress an already compressed texture. It will be decompressed first..");
                Decompress(image, format.IsSRgb());
            }

            var request = new CompressingRequest(format, quality);

            ExecuteRequest(image, request);
        }
Пример #20
0
        /// <summary>
        /// Checks the conformity of a candidate texture with a model one : check the mipmap count and the format.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="candidate">The candidate.</param>
        private void CheckConformity(TexImage model, TexImage candidate)
        {
            if (model.MipmapCount > 1 && candidate.MipmapCount == 1)
            {
                Log.Warning("The given texture has no mipmaps. They will be generated..");
                GenerateMipMaps(candidate, Filter.MipMapGeneration.Box);
            }

            if (candidate.Format != model.Format)
            {
                Log.Warning("The given texture format isn't correct. The texture will be converted..");
                if (model.Format.IsCompressed())
                {
                    if (candidate.Format.IsCompressed()) Decompress(candidate, candidate.Format.IsSRgb());
                    Compress(candidate, model.Format);
                }
                else
                {
                    Decompress(candidate, candidate.Format.IsSRgb());
                    if (candidate.Format != model.Format) Compress(candidate, model.Format);
                }
            }
        }
Пример #21
0
        /// <summary>
        /// Generates the mip maps.
        /// </summary>
        /// <remarks>
        /// If the image is in a compressed format, it will be first decompressed.
        /// </remarks>
        /// <param name="image">The image.</param>
        /// <param name="filter">The filter.</param>
        public void GenerateMipMaps(TexImage image, Filter.MipMapGeneration filter)
        {
            if (image.Format.IsCompressed())
            {
                Log.Warning("You can't generate mipmaps for a compressed texture. It will be decompressed first..");
                Decompress(image, image.Format.IsSRgb());
            }

            ExecuteRequest(image, new MipMapsGenerationRequest(filter));
        }
Пример #22
0
        /// <summary>
        /// Executes the request.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="request">The request.</param>
        /// <exception cref="TextureToolsException">No available library could perform the task :  + request.Type</exception>
        private void ExecuteRequest(TexImage image, IRequest request)
        {
            // First Check if the current library can handle the request
            if (image.CurrentLibrary != null && image.CurrentLibrary.CanHandleRequest(image, request))
            {
                image.CurrentLibrary.Execute(image, request);
            }
            else // Otherwise, it finds another library which can handle the request
            {
                ITexLibrary library;
                if ((library = FindLibrary(image, request)) != null)
                {
                    if (image.Format.IsBGRAOrder() && !library.SupportBGRAOrder())
                    {
                        SwitchChannel(image);
                    }

                    if(image.CurrentLibrary != null) image.CurrentLibrary.EndLibrary(image); // Ending the use of the previous library (mainly to free memory)

                    library.StartLibrary(image); // Preparing the new library : converting TexImage format to the library native format

                    library.Execute(image, request);

                    image.CurrentLibrary = library;
                }
                else // If no library could be found, an exception is thrown
                {
                    Log.Error("No available library could perform the task : " + request.Type);
                    throw new TextureToolsException("No available library could perform the task : " + request.Type);
                }
            }
        }
Пример #23
0
        /// <summary>
        /// Rescales the specified image with the specified factors.
        /// </summary>
        /// <remarks>
        /// The new size will be : width = width * widthFactor and height = height * heightFactor
        /// If the image is in a compressed format, it will be first decompressed.
        /// </remarks>
        /// <param name="image">The image.</param>
        /// <param name="widthFactor">The width factor.</param>
        /// <param name="heightFactor">The height factor.</param>
        /// <param name="filter">The filter.</param>
        public void Rescale(TexImage image, float widthFactor, float heightFactor, Filter.Rescaling filter)
        {
            if (widthFactor <= 0 || heightFactor <= 0)
            {
                Log.Error("The size factors must be positive floats.");
                throw new TextureToolsException("The size factors must be positive floats.");
            }

            // The texture dimension won't change.
            if (widthFactor == 1 && heightFactor ==1)
            {
                return;
            }

            if (image.Format.IsCompressed())
            {
                Log.Warning("You can't rescale a compressed texture. It will be decompressed first..");
                Decompress(image, image.Format.IsSRgb());
            }

            ExecuteRequest(image, new FactorRescalingRequest(widthFactor, heightFactor, filter));
        }
Пример #24
0
        /// <summary>
        /// Creates a texture array with the given TexImage.
        /// </summary>
        /// <param name="textureList">The texture list.</param>
        /// <returns>An instance of <see cref="TexImage"/> corresponding containing the texture array.</returns>
        /// <exception cref="TextureToolsException">
        /// No available library could create the array.
        /// or
        /// The textures must all have the same size and format to be in a texture array.
        /// </exception>
        public TexImage CreateTextureArray(List<TexImage> textureList)
        {
            var array = new TexImage();
            var request = new ArrayCreationRequest(textureList);

            ITexLibrary library = FindLibrary(array, request);
            if (library == null)
            {
                Log.Error("No available library could create the array.");
                throw new TextureToolsException("No available library could create the array.");
            }

            int width = textureList[0].Width;
            int height = textureList[0].Height;
            int depth = textureList[0].Depth;
            array.Format = textureList[0].Format;

            foreach (var texture in textureList)
            {
                texture.Update();
                if (texture.Width != width || texture.Height != height || texture.Depth != depth || texture.Format != array.Format)
                {
                    Log.Error("The textures must all have the same size and format to be in a texture array.");
                    throw new TextureToolsException("The textures must all have the same size and format to be in a texture array.");
                }
            }
  
            ExecuteRequest(array, request);

            return array;
        }
Пример #25
0
        /// <summary>
        /// Premultiplies the alpha.
        /// </summary>
        /// <param name="image">The image.</param>
        public void PreMultiplyAlpha(TexImage image)
        {
            if (image.Format.IsCompressed())
            {
                Log.Warning("You can't premultiply alpha on a compressed texture. It will be decompressed first..");
                Decompress(image, image.Format.IsSRgb());
            }

            ExecuteRequest(image, new PreMultiplyAlphaRequest());
        }
Пример #26
0
        /// <summary>
        /// Creates a texture cube with the given TexImage.
        /// </summary>
        /// <param name="textureList">The texture list.</param>
        /// <returns>An instance of <see cref="TexImage"/> containing the texture cube.</returns>
        /// <exception cref="TextureToolsException">
        /// No available library could create the cube.
        /// or
        /// The number of texture in the texture list must be a multiple of 6.
        /// or
        /// The textures must all have the same size and format to be in a texture cube.
        /// </exception>
        public TexImage CreateTextureCube(List<TexImage> textureList)
        {
            var cube = new TexImage();
            var request = new CubeCreationRequest(textureList);

            if (textureList.Count % 6 != 0)
            {
                Log.Error("The number of texture in the texture list must be a multiple of 6.");
                throw new TextureToolsException("The number of texture in the texture list must be a multiple of 6.");
            }

            ITexLibrary library = FindLibrary(cube, request);
            if (library == null)
            {
                Log.Error("No available library could create the cube.");
                throw new TextureToolsException("No available library could create the cube.");
            }

            int width = textureList[0].Width;
            int height = textureList[0].Height;
            int depth = textureList[0].Depth;
            cube.Format = textureList[0].Format;

            foreach (var texture in textureList)
            {
                texture.Update();
                if (texture.Width != width || texture.Height != height || texture.Depth != depth || texture.Format != cube.Format)
                {
                    Log.Error("The textures must all have the same size and format to be in a texture cube.");
                    throw new TextureToolsException("The textures must all have the same size and format to be in a texture cube.");
                }
            }

            ExecuteRequest(cube, request);

            return cube;
        }
Пример #27
0
        /// <summary>
        /// Pick the color under the specified pixel.
        /// </summary>
        /// <param name="texture">The texture</param>
        /// <param name="pixel">The coordinate of the pixel</param>
        public unsafe Color PickColor(TexImage texture, Int2 pixel)
        {
            if (texture == null) throw new ArgumentNullException(nameof(texture));

            var format = texture.Format;
            if (texture.Dimension != TexImage.TextureDimension.Texture2D || !(format.IsRGBAOrder() || format.IsBGRAOrder() || format.SizeInBytes() != 4))
                throw new NotImplementedException();

            // check that the pixel is inside the texture
            var textureRegion = new Rectangle(0, 0, texture.Width, texture.Height);
            if (!textureRegion.Contains(pixel))
                throw new ArgumentException("The provided pixel coordinate is outside of the texture");

            var ptr = (uint*)texture.Data;
            var stride = texture.RowPitch / 4;

            var pixelColorInt = ptr[stride*pixel.Y + pixel.X];
            var pixelColor = format.IsRGBAOrder() ? Color.FromRgba(pixelColorInt) : Color.FromBgra(pixelColorInt);

            return pixelColor;
        }
Пример #28
0
        /// <summary>
        /// Loads the specified request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>An instance of the class <see cref="TexImage"/> containing your loaded image</returns>
        /// <exception cref="TextureToolsException">No available library could perform the task : LoadingRequest</exception>
        private TexImage Load(LoadingRequest request)
        {
            var texImage = new TexImage();
            texImage.Name = request.FilePath == null ? "" : Path.GetFileName(request.FilePath);

            foreach (ITexLibrary library in textureLibraries)
            {
                if (library.CanHandleRequest(texImage, request))
                {
                    library.Execute(texImage, request);
                    texImage.CurrentLibrary = library;
                    return texImage;
                }
            }

            Log.Error("No available library could load your texture : " + request.Type);
            throw new TextureToolsException("No available library could perform the task : " + request.Type);
        }
Пример #29
0
        /// <summary>
        /// Create a new image from region.
        /// </summary>
        /// <param name="texImage">The original image from which to extract the region</param>
        /// <param name="region">The region from the original image to extract.</param>
        /// <returns>The extracted region <see cref="TexImage"/>. Note: it is the user responsibility to dispose the returned image.</returns>
        public unsafe Image CreateImageFromRegion(TexImage texImage, Rectangle region)
        {
            if (texImage.Dimension != TexImage.TextureDimension.Texture2D || texImage.Format.IsCompressed())
                throw new NotImplementedException();

            Log.Info("Extracting region and exporting to Paradox Image ...");

            // clamp the provided region to be sure it fits in provided image
            region.X = Math.Max(0, Math.Min(region.X, texImage.Width));
            region.Y = Math.Max(0, Math.Min(region.Y, texImage.Height));
            region.Width = Math.Max(0, Math.Min(region.Width, texImage.Width - region.X));
            region.Height = Math.Max(0, Math.Min(region.Height, texImage.Height - region.Y));

            // create the paradox image
            var pdxImage = Image.New2D(region.Width, region.Height, 1, texImage.Format);
            if (pdxImage == null)
            {
                Log.Error("Image could not be created.");
                throw new InvalidOperationException("Image could not be created.");
            }

            // get the row pitch of the paradox image
            var pixelBuffer = pdxImage.GetPixelBuffer(0, 0);
            var dstRowPitch = pixelBuffer.RowStride;

            // copy the data
            if (texImage.ArraySize > 0)
            {
                var rowSrcPtr = texImage.SubImageArray[0].Data;
                var rowDstPtr = pdxImage.DataPointer;
                rowSrcPtr = IntPtr.Add(rowSrcPtr, region.Y * texImage.RowPitch);
                for (int i = 0; i < region.Height; i++)
                {
                    var pSrc = ((UInt32*)rowSrcPtr) + region.X;
                    var pDst = (UInt32*)rowDstPtr;

                    for (int x = 0; x < region.Width; x++)
                        *(pDst++) = *(pSrc++);

                    rowSrcPtr = IntPtr.Add(rowSrcPtr, texImage.RowPitch);
                    rowDstPtr = IntPtr.Add(rowDstPtr, dstRowPitch);
                }
            }

            return pdxImage;
        }
Пример #30
0
        /// <summary>
        /// Decompresses the specified <see cref="TexImage"/>.
        /// </summary>
        /// <param name="image">The <see cref="TexImage"/>.</param>
        /// <param name="isSRgb">Indicate is the image to decompress is an sRGB image</param>
        public void Decompress(TexImage image, bool isSRgb)
        {
            if (!image.Format.IsCompressed())
            {
                return;
            }

            ExecuteRequest(image, new DecompressingRequest(isSRgb, image.Format));
        }
Пример #31
0
        /// <summary>
        /// Corrects the gamma.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="gamma">The gamma.</param>
        public void CorrectGamma(TexImage image, double gamma)
        {
            if (gamma <= 0)
            {
                Log.Error("The gamma must be a positive float.");
                throw new TextureToolsException("The gamma must be a positive float.");
            }

            if (image.Format.IsCompressed())
            {
                Log.Warning("You can't correct gamme on a compressed texture. It will be decompressed first..");
                Decompress(image, image.Format.IsSRgb());
            }

            var request = new GammaCorrectionRequest(gamma);

            ExecuteRequest(image, request);
        }
Пример #32
0
        /// <summary>
        /// Saves the specified <see cref="TexImage"/> into a file.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="fileName">Name of the file.</param>
        /// <param name="minimumMipMapSize">Minimum size of the mip map.</param>
        public void Save(TexImage image, String fileName, int minimumMipMapSize=1)
        {
            if (fileName == null || fileName.Equals(""))
            {
                Log.Error("No file name entered.");
                throw new TextureToolsException("No file name entered.");
            }

            var request = new ExportRequest(fileName, minimumMipMapSize);

            if (FindLibrary(image, request) == null && image.Format.IsCompressed())
            {
                Log.Warning("No library can export this texture with the actual compression format. We will try to decompress it first.");
                Decompress(image, image.Format.IsSRgb());
            }

            ExecuteRequest(image, request);
        }
Пример #33
0
        /// <summary>
        /// Swaps two slices of a texture array.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="firstIndex">The index of the first sub-image.</param>
        /// <param name="secondIndex">The index of the second sub-image</param>
        public void Swap(TexImage image, int firstIndex, int secondIndex)
        {
            var request = new SwappingRequest(firstIndex, secondIndex);

            ExecuteRequest(image, request);
        }
Пример #34
0
        /// <summary>
        /// Saves the specified <see cref="TexImage"/> into a file with the specified format.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="fileName">Name of the file.</param>
        /// <param name="format">The new format.</param>
        /// <param name="minimumMipMapSize">Minimum size of the mip map.</param>
        public void Save(TexImage image, String fileName, PixelFormat format, int minimumMipMapSize = 1)
        {
            if (fileName == null || fileName.Equals(""))
            {
                Log.Error("No file name entered.");
                throw new TextureToolsException("No file name entered.");
            }

            if (minimumMipMapSize < 0)
            {
                Log.Error("The minimup Mipmap size can't be negative. Put 0 or 1 for a complete Mipmap chain.");
                throw new TextureToolsException("The minimup Mipmap size can't be negative. Put 0 or 1 for a complete Mipmap chain.");
            }

            if (image.Format != format && format.IsCompressed() && !image.Format.IsCompressed())
            {
                TexImage workingImage = (TexImage)image.Clone();
                Compress(workingImage, format);
                ExecuteRequest(workingImage, new ExportRequest(fileName, minimumMipMapSize));
                workingImage.Dispose();
            }
            else if (image.Format != format && format.IsCompressed())
            {
                TexImage workingImage = (TexImage)image.Clone();
                Decompress(workingImage, image.Format.IsSRgb());
                Compress(workingImage, format);
                ExecuteRequest(workingImage, new ExportRequest(fileName, minimumMipMapSize));
                workingImage.Dispose();
            }
            else
            {
                ExecuteRequest(image, new ExportRequest(fileName, minimumMipMapSize));
            }
        }