Exemple #1
0
        /// <summary>
        /// Loads the specified image.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="loader">The loader.</param>
        /// <exception cref="TextureToolsException">If loading failed : mostly not supported format or path error (FileNotFound).</exception>
        private void Load(TexImage image, LoadingRequest loader)
        {
            Log.Verbose("Loading " + loader.FilePath + " ...");

            FIBITMAP          temp;
            FREE_IMAGE_FORMAT fileFormat = FREE_IMAGE_FORMAT.FIF_UNKNOWN;

            try
            {
                temp = FreeImage.LoadEx(loader.FilePath, ref fileFormat);
                FreeImage.FlipVertical(temp);

                if (temp.IsNull)
                {
                    throw new Exception("FreeImage's image data is null");
                }
            }
            catch (Exception e)
            {
                Log.Error("Loading file " + loader.FilePath + " failed: " + e.Message);
                throw new TextureToolsException("Loading file " + loader.FilePath + " failed: " + e.Message);
            }

            // Converting the image into BGRA_8888 format
            var libraryData = new FreeImageTextureLibraryData {
                Bitmaps = new [] { FreeImage.ConvertTo32Bits(temp) }
            };

            image.LibraryData[this] = libraryData;
            int alphaSize = GetAlphaDepth(fileFormat, temp);

            FreeImage.Unload(temp);

            image.Data               = FreeImage.GetBits(libraryData.Bitmaps[0]);
            image.Width              = (int)FreeImage.GetWidth(libraryData.Bitmaps[0]);
            image.Height             = (int)FreeImage.GetHeight(libraryData.Bitmaps[0]);
            image.Depth              = 1;
            image.Dimension          = image.Height == 1 ? TexImage.TextureDimension.Texture1D : TexImage.TextureDimension.Texture2D;
            image.Format             = loader.LoadAsSRgb? PixelFormat.B8G8R8A8_UNorm_SRgb : PixelFormat.B8G8R8A8_UNorm;
            image.OriginalAlphaDepth = alphaSize;

            int rowPitch, slicePitch;

            Tools.ComputePitch(image.Format, image.Width, image.Height, out rowPitch, out slicePitch);
            image.RowPitch   = rowPitch;
            image.SlicePitch = slicePitch;

            //Only one image in the SubImageArray, FreeImage is only used to load images, not textures.
            image.SubImageArray[0].Data       = image.Data;
            image.SubImageArray[0].DataSize   = image.DataSize;
            image.SubImageArray[0].Width      = image.Width;
            image.SubImageArray[0].Height     = image.Height;
            image.SubImageArray[0].RowPitch   = rowPitch;
            image.SubImageArray[0].SlicePitch = slicePitch;
            image.DataSize         = (int)(FreeImage.GetDIBSize(libraryData.Bitmaps[0]) - GetHeaderSize()); // header size of a bitmap is included in their size calculus
            libraryData.Data       = IntPtr.Zero;
            image.DisposingLibrary = this;
        }
Exemple #2
0
        public void Dispose(TexImage image)
        {
            FreeImageTextureLibraryData libraryData = (FreeImageTextureLibraryData)image.LibraryData[this];

            if (libraryData.Data != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(libraryData.Data);
            }
        }
Exemple #3
0
        /// <summary>
        /// Corrects the gamma.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="libraryData">The library data.</param>
        /// <param name="request">The request.</param>
        public void CorrectGamma(TexImage image, FreeImageTextureLibraryData libraryData, GammaCorrectionRequest request)
        {
            Log.Verbose("Applying a gamma correction of " + request.Gamma + " ...");

            foreach (FIBITMAP bitmap in libraryData.Bitmaps)
            {
                FreeImage.AdjustGamma(bitmap, request.Gamma);
            }
        }
Exemple #4
0
        /// <summary>
        /// Exports the specified image to the requested file name.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="libraryData">The library data.</param>
        /// <param name="request">The request.</param>
        /// <exception cref="TexLibraryException">
        /// Export failure.
        /// </exception>
        /// <remarks>
        /// In case of mipmapping or array texture, may images will be output.
        /// </remarks>
        private void Export(TexImage image, FreeImageTextureLibraryData libraryData, ExportRequest request)
        {
            String directory = Path.GetDirectoryName(request.FilePath);
            String fileName  = Path.GetFileNameWithoutExtension(request.FilePath);
            String extension = Path.GetExtension(request.FilePath);
            String finalName;

            if (image.Dimension == TexImage.TextureDimension.Texture3D)
            {
                Log.Error("Not implemented.");
                throw new TextureToolsException("Not implemented.");
            }

            if (!image.Format.IsBgraOrder())
            {
                SwitchChannels(image, libraryData, new SwitchingBRChannelsRequest());
            }

            if (image.SubImageArray.Length > 1 && request.MinimumMipMapSize < FreeImage.GetWidth(libraryData.Bitmaps[0]) && request.MinimumMipMapSize < FreeImage.GetHeight(libraryData.Bitmaps[0]))
            {
                int imageCount = 0;
                for (int i = 0; i < image.ArraySize; ++i)
                {
                    for (int j = 0; j < image.MipmapCount; ++j)
                    {
                        if (FreeImage.GetWidth(libraryData.Bitmaps[imageCount]) < request.MinimumMipMapSize || FreeImage.GetHeight(libraryData.Bitmaps[imageCount]) < request.MinimumMipMapSize)
                        {
                            break;
                        }

                        finalName = directory + "/" + fileName + "-ind_" + i + "-mip_" + j + extension;
                        FreeImage.FlipVertical(libraryData.Bitmaps[imageCount]);
                        if (!FreeImage.SaveEx(libraryData.Bitmaps[imageCount], finalName))
                        {
                            Log.Error("Export failure.");
                            throw new TextureToolsException("Export failure.");
                        }
                        FreeImage.FlipVertical(libraryData.Bitmaps[imageCount]);
                        Log.Verbose("Exporting image to " + finalName + " ...");
                        ++imageCount;
                    }
                }
            }
            else
            {
                FreeImage.FlipVertical(libraryData.Bitmaps[0]);
                if (!FreeImage.SaveEx(libraryData.Bitmaps[0], request.FilePath))
                {
                    Log.Error("Export failure.");
                    throw new TextureToolsException("Export failure.");
                }
                FreeImage.FlipVertical(libraryData.Bitmaps[0]);
                Log.Verbose("Exporting image to " + request.FilePath + " ...");
            }

            image.Save(request.FilePath);
        }
Exemple #5
0
        public void EndLibrary(TexImage image)
        {
            if (!image.LibraryData.ContainsKey(this))
            {
                return;
            }
            FreeImageTextureLibraryData libraryData = (FreeImageTextureLibraryData)image.LibraryData[this];

            IntPtr buffer = Marshal.AllocHGlobal(image.DataSize);
            int    offset = 0;
            int    size, rowPitch, slicePitch;

            image.SubImageArray = new TexImage.SubImage[libraryData.Bitmaps.Length];

            try
            {
                for (int i = 0; i < libraryData.Bitmaps.Length; ++i)
                {
                    image.SubImageArray[i].Width  = (int)FreeImage.GetWidth(libraryData.Bitmaps[i]);
                    image.SubImageArray[i].Height = (int)FreeImage.GetHeight(libraryData.Bitmaps[i]);

                    Tools.ComputePitch(image.Format, image.SubImageArray[i].Width, image.SubImageArray[i].Height, out rowPitch, out slicePitch);
                    size = slicePitch;

                    image.SubImageArray[i].Data       = new IntPtr(buffer.ToInt64() + offset);
                    image.SubImageArray[i].DataSize   = size;
                    image.SubImageArray[i].RowPitch   = rowPitch;
                    image.SubImageArray[i].SlicePitch = slicePitch;

                    Utilities.CopyMemory(image.SubImageArray[i].Data, FreeImage.GetBits(libraryData.Bitmaps[i]), size);
                    offset += size;
                }
            }
            catch (AccessViolationException e)
            {
                Log.Error("Failed to convert FreeImage native data to TexImage texture. ", e);
                throw new TextureToolsException("Failed to convert FreeImage native data to TexImage texture. ", e);
            }

            image.Data       = image.SubImageArray[0].Data;
            libraryData.Data = image.Data;

            // Freeing native Data, the texture data has been copied.
            for (int i = 0; i < libraryData.Bitmaps.Length; ++i)
            {
                FreeImage.Unload(libraryData.Bitmaps[i]);
            }

            libraryData.Bitmaps    = null;
            image.DisposingLibrary = this;
        }
Exemple #6
0
        public void Execute(TexImage image, IRequest request)
        {
            FreeImageTextureLibraryData libraryData = image.LibraryData.TryGetValue(this, out var libData) ? (FreeImageTextureLibraryData)libData : null;

            switch (request.Type)
            {
            case RequestType.Loading:
                Load(image, (LoadingRequest)request);
                break;

            case RequestType.Rescaling:
                Rescale(image, libraryData, (RescalingRequest)request);
                break;

            case RequestType.SwitchingChannels:
                SwitchChannels(image, libraryData, (SwitchingBRChannelsRequest)request);
                break;

            case RequestType.Flipping:
                Flip(image, libraryData, (FlippingRequest)request);
                break;

            case RequestType.FlippingSub:
                FlipSub(image, libraryData, (FlippingSubRequest)request);
                break;

            case RequestType.Swapping:
                Swap(image, libraryData, (SwappingRequest)request);
                break;

            case RequestType.Export:
                Export(image, libraryData, (ExportRequest)request);
                break;

            case RequestType.GammaCorrection:
                CorrectGamma(image, libraryData, (GammaCorrectionRequest)request);
                break;

            default:
                Log.Error("FITexLib (FreeImage) can't handle this request: " + request.Type);
                throw new TextureToolsException("FITexLib (FreeImage) can't handle this request: " + request.Type);
            }
        }
Exemple #7
0
        /// <summary>
        /// Flips the specified image horizontally or vertically.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="libraryData">The library data.</param>
        /// <param name="flip">The flip request.</param>
        private void Flip(TexImage image, FreeImageTextureLibraryData libraryData, FlippingRequest flip)
        {
            Log.Verbose("Flipping image : " + flip.Flip + " ...");

            for (int i = 0; i < libraryData.Bitmaps.Length; ++i)
            {
                switch (flip.Flip)
                {
                case Orientation.Vertical:
                    FreeImage.FlipVertical(libraryData.Bitmaps[i]);
                    break;

                case Orientation.Horizontal:
                    FreeImage.FlipHorizontal(libraryData.Bitmaps[i]);
                    break;
                }
            }

            image.Flip(flip.Flip);
        }
Exemple #8
0
        /// <summary>
        /// Swaps two sub-images.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="libraryData">The library data.</param>
        /// <param name="swap">The swap request.</param>
        private void Swap(TexImage image, FreeImageTextureLibraryData libraryData, SwappingRequest swap)
        {
            Log.Verbose("Swapping image : sub-image " + swap.FirstSubImageIndex + " and " + swap.SecondSubImageIndex + " ...");

            if (swap.FirstSubImageIndex >= 0 && swap.FirstSubImageIndex < libraryData.Bitmaps.Length &&
                swap.SecondSubImageIndex >= 0 && swap.SecondSubImageIndex < libraryData.Bitmaps.Length)
            {
                // copy first image
                var firstImage = FreeImage.Copy(libraryData.Bitmaps[swap.FirstSubImageIndex], 0, 0, image.Width, image.Height);
                FreeImage.Paste(libraryData.Bitmaps[swap.FirstSubImageIndex], libraryData.Bitmaps[swap.SecondSubImageIndex], 0, 0, 256);
                FreeImage.Paste(libraryData.Bitmaps[swap.SecondSubImageIndex], firstImage, 0, 0, 256);

                // TODO: free firstImage?
            }
            else
            {
                Log.Warning("Cannot swap the sub-images " + swap.FirstSubImageIndex + " and " + swap.SecondSubImageIndex + " because there is only " + libraryData.Bitmaps.Length + " sub-images.");
            }

            // TODO: texture atlas update?
        }
Exemple #9
0
        public void StartLibrary(TexImage image)
        {
            if (image.Format.IsCompressed())
            {
                Log.Error("FreeImage can't process compressed texture.");
                throw new TextureToolsException("FreeImage can't process compressed texture.");
            }

            var libraryData = new FreeImageTextureLibraryData();

            image.LibraryData[this] = libraryData;

            libraryData.Bitmaps = new FIBITMAP[image.SubImageArray.Length];

            FREE_IMAGE_TYPE type;
            uint            bpp, redMask, greenMask, blueMask;

            if (!FreeImage.GetFormatParameters(image.Format, out type, out bpp, out redMask, out greenMask, out blueMask))
            {
                throw new ArgumentException("The pixel format '{0}' is not supported by FreeImage".ToFormat(image.Format));
            }
            for (int i = 0; i < image.SubImageArray.Length; ++i)
            {
                var data   = image.SubImageArray[i].Data;
                var width  = image.SubImageArray[i].Width;
                var heigth = image.SubImageArray[i].Height;
                var pitch  = image.SubImageArray[i].RowPitch;
                libraryData.Bitmaps[i] = FreeImage.ConvertFromRawBits(data, type, width, heigth, pitch, bpp, redMask, greenMask, blueMask, false);
            }

            if (image.DisposingLibrary != null)
            {
                image.DisposingLibrary.Dispose(image);
            }

            image.DisposingLibrary = this;

            libraryData.Data = IntPtr.Zero;
        }
Exemple #10
0
        /// <summary>
        /// Switches the channels R and B.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="libraryData">The library data.</param>
        /// <param name="switchC">The switch request</param>
        /// <remarks>
        /// Some libraries can't handle BGRA order so we need to change it to RGBA.
        /// </remarks>
        private void SwitchChannels(TexImage image, FreeImageTextureLibraryData libraryData, SwitchingBRChannelsRequest switchC)
        {
            Log.Verbose("Switching channels R and G ...");

            for (int i = 0; i < libraryData.Bitmaps.Length; ++i)
            {
                FIBITMAP blueChannel = FreeImage.GetChannel(libraryData.Bitmaps[i], FREE_IMAGE_COLOR_CHANNEL.FICC_BLUE);
                FIBITMAP redChannel  = FreeImage.GetChannel(libraryData.Bitmaps[i], FREE_IMAGE_COLOR_CHANNEL.FICC_RED);
                FreeImage.SetChannel(libraryData.Bitmaps[i], redChannel, FREE_IMAGE_COLOR_CHANNEL.FICC_BLUE);
                FreeImage.SetChannel(libraryData.Bitmaps[i], blueChannel, FREE_IMAGE_COLOR_CHANNEL.FICC_RED);
                FreeImage.Unload(blueChannel);
                FreeImage.Unload(redChannel);
            }

            if (image.Format.IsBgraOrder())
            {
                image.Format = PixelFormat.R8G8B8A8_UNorm;
            }
            else
            {
                image.Format = PixelFormat.B8G8R8A8_UNorm;
            }
        }
Exemple #11
0
        /// <summary>
        /// Flips the specified sub-image horizontally or vertically.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="libraryData">The library data.</param>
        /// <param name="flipSub">The flip request.</param>
        private void FlipSub(TexImage image, FreeImageTextureLibraryData libraryData, FlippingSubRequest flipSub)
        {
            Log.Verbose("Flipping image : sub-image " + flipSub.SubImageIndex + " " + flipSub.Flip + " ...");

            if (flipSub.SubImageIndex >= 0 && flipSub.SubImageIndex < libraryData.Bitmaps.Length)
            {
                switch (flipSub.Flip)
                {
                case Orientation.Vertical:
                    FreeImage.FlipVertical(libraryData.Bitmaps[flipSub.SubImageIndex]);
                    break;

                case Orientation.Horizontal:
                    FreeImage.FlipHorizontal(libraryData.Bitmaps[flipSub.SubImageIndex]);
                    break;
                }
            }
            else
            {
                Log.Warning("Cannot flip the sub-image " + flipSub.SubImageIndex + " because there is only " + libraryData.Bitmaps.Length + " sub-images.");
            }

            // TODO: texture atlas update?
        }
Exemple #12
0
        /// <summary>
        /// Rescales the specified image.
        /// </summary>
        /// <remarks>
        /// The MipmapCount will be reset to 1 after this operation
        /// </remarks>
        /// <param name="image">The image.</param>
        /// <param name="libraryData">The library data.</param>
        /// <param name="rescale">The rescale.</param>
        private void Rescale(TexImage image, FreeImageTextureLibraryData libraryData, RescalingRequest rescale)
        {
            int width  = rescale.ComputeWidth(image);
            int height = rescale.ComputeHeight(image);

            Log.Verbose("Rescaling image to " + width + "x" + height + " with " + rescale.Filter + " ...");

            FIBITMAP[] newTab;

            if (image.Dimension == TexImage.TextureDimension.Texture3D) // in case of 3D Texture, we must rescale each slice of the top mipmap level
            {
                newTab = new FIBITMAP[image.ArraySize * image.FaceCount * image.Depth];
                int curDepth;

                int nbSubImageWithMipMapPerArrayMemeber = 0; // calculating the number of sub images we have to jump to reach the next top level mipmap of the next array member
                curDepth = image.Depth;
                for (int i = 0; i < image.MipmapCount; ++i)
                {
                    nbSubImageWithMipMapPerArrayMemeber += curDepth;
                    curDepth = curDepth > 1 ? curDepth >>= 1 : curDepth;
                }

                int ct = 0;
                for (int j = 0; j < image.ArraySize; ++j)
                {
                    for (int i = 0; i < image.Depth; ++i)
                    {
                        newTab[ct] = FreeImage.Rescale(libraryData.Bitmaps[i + j * nbSubImageWithMipMapPerArrayMemeber], width, height, (FREE_IMAGE_FILTER)rescale.Filter);
                        ++ct;
                    }
                }
            }
            else
            {
                newTab = new FIBITMAP[image.ArraySize];
                int ct = 0;
                for (int i = 0; i < libraryData.Bitmaps.Length; i += image.MipmapCount)
                {
                    newTab[ct] = FreeImage.Rescale(libraryData.Bitmaps[i], width, height, (FREE_IMAGE_FILTER)rescale.Filter);
                    ++ct;
                }
            }

            for (int i = 0; i < libraryData.Bitmaps.Length; ++i)
            {
                FreeImage.Unload(libraryData.Bitmaps[i]);
            }

            libraryData.Bitmaps = newTab;
            image.Data          = FreeImage.GetBits(newTab[0]);

            // Updating image data
            image.Rescale(width, height);

            int rowPitch, slicePitch;

            Tools.ComputePitch(image.Format, width, height, out rowPitch, out slicePitch);

            image.RowPitch    = rowPitch;
            image.SlicePitch  = slicePitch;
            image.MipmapCount = 1;
            image.DataSize    = image.SlicePitch * image.ArraySize * image.FaceCount * image.Depth;
        }