/// <summary>
        /// Function to create 2D Gorgon image data from a single System.Drawing.Image.
        /// </summary>
        /// <param name="wic">Windows Imaging Component interface to use.</param>
        /// <param name="image">An image to convert.</param>
        /// <param name="options">Options for conversion.</param>
        /// <returns>The converted image data.</returns>
        public static GorgonImageData Create2DImageDataFromImage(GorgonWICImage wic, Image image, GorgonGDIOptions options)
        {
            if (options.Format == BufferFormat.Unknown)
            {
                options.Format = GetBufferFormat(image.PixelFormat);
            }

            if (options.Format == BufferFormat.Unknown)
            {
                throw new GorgonException(GorgonResult.FormatNotSupported,
                                          string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, image.PixelFormat));
            }

            if (options.Width < 1)
            {
                options.Width = image.Width;
            }

            if (options.Height < 1)
            {
                options.Height = image.Height;
            }

            // Specify 0 to generate a full mip chain.
            options.MipCount = options.MipCount < 1
                                                   ? GorgonImageData.GetMaxMipCount(options.Width, options.Height)
                                                   : options.MipCount.Min(GorgonImageData.GetMaxMipCount(options.Width, options.Height));

            // Create our settings.
            var settings = new GorgonTexture2DSettings
            {
                Width      = options.Width,
                Height     = options.Height,
                MipCount   = options.MipCount,
                ArrayCount = 1,
                Format     = options.Format,
                AllowUnorderedAccessViews = options.AllowUnorderedAccess,
                ShaderViewFormat          = options.ViewFormat,
                Usage = options.Usage
            };

            // Create our image data.
            var data = new GorgonImageData(settings);

            // Using the image, convert to a WIC bitmap object.
            using (Bitmap bitmap = wic.CreateWICImageFromImage(image))
            {
                for (int mipLevel = 0; mipLevel < options.MipCount; mipLevel++)
                {
                    var buffer = data.Buffers[mipLevel];
                    wic.AddWICBitmapToImageData(bitmap, options.Filter, options.Dither, buffer, options.UseClipping);
                }
            }

            return(data);
        }
Example #2
0
        /// <summary>
        /// Function to perform any post processing on image data.
        /// </summary>
        internal void PostProcess(GorgonImageData data)
        {
            IImageSettings destSettings = data.Settings.Clone();
            int            width        = Width > 0 ? Width : data.Settings.Width;
            int            height       = Height > 0 ? Height : data.Settings.Height;
            int            mipCount     = MipCount > 0 ? MipCount : data.Settings.MipCount;
            BufferFormat   format       = (Format != BufferFormat.Unknown) ? Format : data.Settings.Format;
            Rectangle      newSize      = Rectangle.Empty;
            int            mipStart     = 0;
            var            sourceInfo   = GorgonBufferFormatInfo.GetInfo(data.Settings.Format);
            var            destInfo     = GorgonBufferFormatInfo.GetInfo(format);

            // First, confirm whether we can perform format conversions.
            using (var wic = new GorgonWICImage())
            {
                Guid srcPixelFormat  = wic.GetGUID(data.Settings.Format);
                Guid destPixelFormat = wic.GetGUID(format);

                // Do nothing if we can't do anything with the source format.
                if (srcPixelFormat == Guid.Empty)
                {
                    return;
                }

                // Cancel conversion if we're using the same format.
                if (srcPixelFormat == destPixelFormat)
                {
                    destPixelFormat = Guid.Empty;
                }

                // Get the new size.
                if ((width != data.Settings.Width) || (height != data.Settings.Height))
                {
                    newSize = new Rectangle(0, 0, width, height);
                }

                // Set up destination buffer settings.
                destSettings.Format   = format;
                destSettings.Width    = width;
                destSettings.Height   = height;
                destSettings.MipCount = mipCount;

                // Ensure we don't go over the maximum.
                int maxMips = GorgonImageData.GetMaxMipCount(destSettings);

                if (mipCount > maxMips)
                {
                    mipCount = maxMips;
                }

                // Nothing's going to happen here, so leave.
                if ((destPixelFormat == Guid.Empty) && (newSize == Rectangle.Empty) && (mipCount == 1))
                {
                    return;
                }

                // Create our worker buffer.
                GorgonImageData destData;
                using (destData = new GorgonImageData(destSettings))
                {
                    // The first step is to convert and resize our images:
                    if ((destPixelFormat != Guid.Empty) || (newSize != Rectangle.Empty))
                    {
                        for (int array = 0; array < destSettings.ArrayCount; array++)
                        {
                            // We're not going to copy mip levels at this point, that will come in the next step.
                            for (int depth = 0; depth < destSettings.Depth; depth++)
                            {
                                // Get our source/destination buffers.
                                var sourceBuffer = data.Buffers[0, data.Settings.ImageType == ImageType.Image3D ? depth : array];
                                var destBuffer   = destData.Buffers[0, data.Settings.ImageType == ImageType.Image3D ? depth : array];

                                var dataRect = new DataRectangle(sourceBuffer.Data.BasePointer, sourceBuffer.PitchInformation.RowPitch);

                                // Create a temporary WIC bitmap to work with.
                                using (var bitmap = new Bitmap(wic.Factory, sourceBuffer.Width, sourceBuffer.Height, srcPixelFormat, dataRect, sourceBuffer.PitchInformation.SlicePitch))
                                {
                                    wic.TransformImageData(bitmap,
                                                           destBuffer.Data.BasePointer,
                                                           destBuffer.PitchInformation.RowPitch,
                                                           destBuffer.PitchInformation.SlicePitch,
                                                           destPixelFormat,
                                                           sourceInfo.IssRGB,
                                                           destInfo.IssRGB,
                                                           Dithering,
                                                           newSize,
                                                           Clip,
                                                           Filter);
                                }
                            }
                        }

                        // Adjust the mip map starting point.
                        mipStart = 1;
                    }

                    // Next, we need to build mip maps.
                    if (destSettings.MipCount > 1)
                    {
                        // The first step is to convert and resize our images:
                        for (int array = 0; array < destSettings.ArrayCount; array++)
                        {
                            int mipDepth = destSettings.Depth;

                            for (int mip = mipStart; mip < destSettings.MipCount; mip++)
                            {
                                // We're not going to copy mip levels at this point, that will come in the next step.
                                for (int depth = 0; depth < mipDepth; depth++)
                                {
                                    // Get our source/destination buffers.
                                    var sourceBuffer = destData.Buffers[0, data.Settings.ImageType == ImageType.Image3D ? (destSettings.Depth / mipDepth) * depth : array];
                                    var destBuffer   = destData.Buffers[mip, data.Settings.ImageType == ImageType.Image3D ? depth : array];

                                    var dataRect = new DataRectangle(sourceBuffer.Data.BasePointer, sourceBuffer.PitchInformation.RowPitch);

                                    // Create a temporary WIC bitmap to work with.
                                    using (var bitmap = new Bitmap(wic.Factory, sourceBuffer.Width, sourceBuffer.Height, srcPixelFormat, dataRect, sourceBuffer.PitchInformation.SlicePitch))
                                    {
                                        wic.TransformImageData(bitmap, destBuffer.Data.BasePointer, destBuffer.PitchInformation.RowPitch, destBuffer.PitchInformation.SlicePitch,
                                                               Guid.Empty, false, false, ImageDithering.None, new Rectangle(0, 0, destBuffer.Width, destBuffer.Height), false, Filter);
                                    }
                                }

                                if (mipDepth > 1)
                                {
                                    mipDepth >>= 1;
                                }
                            }
                        }
                    }

                    // Update our data.
                    data.TakeOwnership(destData);
                }
            }
        }
        /// <summary>
        /// Function to create a 3D Gorgon image data from multiple System.Drawing.Images.
        /// </summary>
        /// <param name="wic">Windows Imaging Component interface to use.</param>
        /// <param name="images">Images to convert.</param>
        /// <param name="options">Conversion options.</param>
        /// <returns>The converted image data.</returns>
        public static GorgonImageData Create3DImageDataFromImages(GorgonWICImage wic, IList <Image> images, GorgonGDIOptions options)
        {
            if (options.Format == BufferFormat.Unknown)
            {
                options.Format = GetBufferFormat(images[0].PixelFormat);
            }

            if (options.Format == BufferFormat.Unknown)
            {
                throw new GorgonException(GorgonResult.FormatNotSupported,
                                          string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, images[0].PixelFormat));
            }

            if (images.Any(item => item.PixelFormat != images[0].PixelFormat))
            {
                throw new GorgonException(GorgonResult.CannotCreate,
                                          string.Format(Resources.GORGFX_IMAGE_MUST_BE_SAME_FORMAT, images[0].PixelFormat));
            }

            if (options.Width <= 0)
            {
                options.Width = images[0].Width;
            }

            if (options.Height <= 0)
            {
                options.Height = images[0].Height;
            }

            if (options.Depth < 1)
            {
                options.Depth = 1;
            }

            options.MipCount = options.MipCount < 1
                                                   ? 1
                                                   : options.MipCount.Min(GorgonImageData.GetMaxMipCount(options.Width, options.Height,
                                                                                                         options.Depth));

            // Set the depth to the number of images if there are no mip-maps.
            if ((images.Count > 1) && (options.MipCount == 1))
            {
                options.Depth = images.Count;
            }

            // Create our settings.
            var settings = new GorgonTexture3DSettings
            {
                Width    = options.Width,
                Height   = options.Height,
                Depth    = options.Depth,
                MipCount = options.MipCount,
                Format   = options.Format,
                AllowUnorderedAccessViews = options.AllowUnorderedAccess,
                ShaderViewFormat          = options.ViewFormat,
                Usage = options.Usage
            };

            // Only volume textures that are size to a power of 2 can have mip maps.
            if ((!settings.IsPowerOfTwo) && (options.MipCount > 1))
            {
                throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_IMAGE_VOLUME_NOT_POWER_OF_TWO);
            }

            // Create our image data.
            var data = new GorgonImageData(settings);

            int depthMip   = options.Depth;
            int imageIndex = 0;

            for (int mipLevel = 0; mipLevel < data.Settings.MipCount; mipLevel++)
            {
                if (imageIndex >= images.Count)
                {
                    data.Dispose();
                    throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_IMAGE_VOLUME_MIPCOUNT_DEPTHCOUNT_TOO_LARGE);
                }

                for (int depth = 0; depth < depthMip; depth++)
                {
                    var image = images[imageIndex + depth];

                    // Skip NULL images.
                    if (image == null)
                    {
                        continue;
                    }

                    // Using the image, convert to a WIC bitmap object.
                    using (var bitmap = wic.CreateWICImageFromImage(image))
                    {
                        var buffer = data.Buffers[mipLevel, depth];
                        wic.AddWICBitmapToImageData(bitmap, options.Filter, options.Dither, buffer, options.UseClipping);
                    }
                }

                imageIndex += depthMip;

                // Decrease depth based on mip level.
                if (depthMip > 1)
                {
                    depthMip >>= 1;
                }
            }

            return(data);
        }
        /// <summary>
        /// Function to create 2D Gorgon image data from multiple single System.Drawing.Images.
        /// </summary>
        /// <param name="wic">Windows Imaging Component interface to use.</param>
        /// <param name="images">Images to convert.</param>
        /// <param name="options">Options for conversion.</param>
        /// <returns>The converted image data.</returns>
        public static GorgonImageData Create2DImageDataFromImages(GorgonWICImage wic, IList <Image> images, GorgonGDIOptions options)
        {
            if (options.Format == BufferFormat.Unknown)
            {
                options.Format = GetBufferFormat(images[0].PixelFormat);
            }

            if (options.Format == BufferFormat.Unknown)
            {
                throw new GorgonException(GorgonResult.FormatNotSupported,
                                          string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, images[0].PixelFormat));
            }

            if (images.Any(item => item.PixelFormat != images[0].PixelFormat))
            {
                throw new GorgonException(GorgonResult.CannotCreate,
                                          string.Format(Resources.GORGFX_IMAGE_MUST_BE_SAME_FORMAT, images[0].PixelFormat));
            }

            if (options.Width < 1)
            {
                options.Width = images[0].Width;
            }

            if (options.Height < 1)
            {
                options.Height = images[0].Height;
            }

            if (options.ArrayCount < 1)
            {
                options.ArrayCount = 1;
            }

            options.MipCount = options.MipCount < 1
                                                   ? 1
                                                   : options.MipCount.Min(GorgonImageData.GetMaxMipCount(options.Width, options.Height));

            // Create our settings.
            var settings = new GorgonTexture2DSettings
            {
                Width      = options.Width,
                Height     = options.Height,
                MipCount   = options.MipCount,
                ArrayCount = options.ArrayCount,
                Format     = options.Format,
                AllowUnorderedAccessViews = options.AllowUnorderedAccess,
                ShaderViewFormat          = options.ViewFormat,
                Usage = options.Usage
            };

            if ((options.ArrayCount * options.MipCount) > images.Count)
            {
                throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_IMAGE_MIPCOUNT_ARRAYCOUNT_TOO_LARGE);
            }

            // Create our image data.
            var data = new GorgonImageData(settings);

            for (int array = 0; array < data.Settings.ArrayCount; array++)
            {
                for (int mipLevel = 0; mipLevel < data.Settings.MipCount; mipLevel++)
                {
                    var image = images[array * data.Settings.MipCount + mipLevel];

                    if (image == null)
                    {
                        continue;
                    }

                    // Using the image, convert to a WIC bitmap object.
                    using (var bitmap = wic.CreateWICImageFromImage(image))
                    {
                        var buffer = data.Buffers[mipLevel, array];

                        wic.AddWICBitmapToImageData(bitmap, options.Filter, options.Dither, buffer, options.UseClipping);
                    }
                }
            }

            return(data);
        }