Exemplo n.º 1
1
        private static Texture DecodeMultiframe(ImagingFactory imagingFactory, WicFlags flags, TextureDescription description, BitmapDecoder decoder)
        {
            var texture = new Texture(description);
              Guid dstFormat = ToWic(description.Format, false);

              for (int index = 0; index < description.ArraySize; ++index)
              {
            var image = texture.Images[index];
            using (var frame = decoder.GetFrame(index))
            {
              var pfGuid = frame.PixelFormat;
              var size = frame.Size;

              if (size.Width == description.Width && size.Height == description.Height)
              {
            // This frame does not need resized
            if (pfGuid == dstFormat)
            {
              frame.CopyPixels(image.Data, image.RowPitch);
            }
            else
            {
              using (var converter = new FormatConverter(imagingFactory))
              {
                converter.Initialize(frame, dstFormat, GetWicDither(flags), null, 0, BitmapPaletteType.Custom);
                converter.CopyPixels(image.Data, image.RowPitch);
              }
            }
              }
              else
              {
            // This frame needs resizing
            using (var scaler = new BitmapScaler(imagingFactory))
            {
              scaler.Initialize(frame, description.Width, description.Height, GetWicInterp(flags));

              Guid pfScaler = scaler.PixelFormat;
              if (pfScaler == dstFormat)
              {
                scaler.CopyPixels(image.Data, image.RowPitch);
              }
              else
              {
                // The WIC bitmap scaler is free to return a different pixel format than the source image, so here we
                // convert it to our desired format
                using (var converter = new FormatConverter(imagingFactory))
                {
                  converter.Initialize(scaler, dstFormat, GetWicDither(flags), null, 0, BitmapPaletteType.Custom);
                  converter.CopyPixels(image.Data, image.RowPitch);
                }
              }
            }
              }
            }
              }

              return texture;
        }
Exemplo n.º 2
0
        public static Texture2D LoadTexture(IGraphicsService graphicsService, string fileName)
        {
            if (fileName == null)
            {
                throw new ArgumentNullException(nameof(fileName));
            }
            if (fileName.Length == 0)
            {
                throw new ArgumentException("The file name must not be empty.", nameof(fileName));
            }

            // Load API-independent texture.
            Texture texture = null;

            using (var stream = File.OpenRead(fileName))
            {
                string extension = Path.GetExtension(fileName);
                if (!string.IsNullOrEmpty(extension))
                {
                    extension = extension.ToUpperInvariant();
                    if (extension == ".DDS")
                    {
                        texture = DdsHelper.Load(stream, DdsFlags.ForceRgb | DdsFlags.ExpandLuminance);
                    }
                    else if (extension == ".TGA")
                    {
                        texture = TgaHelper.Load(stream);
                    }
                }

                if (texture == null)
                {
                    // TODO: Register ImagingFactory as service.
                    using (var imagingFactory = new ImagingFactory())
                        texture = WicHelper.Load(imagingFactory, stream, WicFlags.ForceRgb | WicFlags.No16Bpp);
                }
            }

            //Tests(texture);

            // Convert to XNA texture.
            var description = texture.Description;

            if (description.Dimension == TextureDimension.TextureCube)
            {
                var texture2D = new Texture2D(graphicsService.GraphicsDevice, description.Width, description.Height, false, description.Format.ToSurfaceFormat());
                texture2D.SetData(texture.Images[0].Data);
                return(texture2D);
            }
            else
            {
                var texture2D = new Texture2D(graphicsService.GraphicsDevice, description.Width, description.Height, description.MipLevels > 1, description.Format.ToSurfaceFormat());
                for (int i = 0; i < texture.Description.MipLevels; i++)
                {
                    texture2D.SetData(i, null, texture.Images[i].Data, 0, texture.Images[i].Data.Length);
                }

                return(texture2D);
            }
        }
Exemplo n.º 3
0
 public OutputHandler(Texture texture)
 {
     _texture = texture;
 }
Exemplo n.º 4
0
        /// <summary>
        /// Resizes the specified texture and/or generates mipmaps.
        /// </summary>
        /// <param name="texture">The texture.</param>
        /// <param name="width">The desired width.</param>
        /// <param name="height">The desired height.</param>
        /// <param name="inputGamma">The input gamma.</param>
        /// <param name="outputGamma">The output gamma.</param>
        /// <param name="generateMipmaps">
        /// <see langword="true"/> to generate all mipmap levels; otherwise <see langword="false"/>.
        /// </param>
        /// <param name="hasAlpha">
        /// <see langword="true"/> if <paramref name="texture"/> requires an alpha channel; otherwise,
        /// <see langword="false"/> if <paramref name="texture"/> is opaque.
        /// </param>
        /// <param name="hasFractionalAlpha">
        /// <see langword="true"/> if <paramref name="texture"/> contains fractional alpha values;
        /// otherwise, <see langword="false"/> if <paramref name="texture"/> is opaque or contains only
        /// binary alpha.
        /// </param>
        /// <param name="premultipliedAlpha">
        /// <see langword="true"/> when <paramref name="texture"/> is using premultiplied alpha.;
        /// otherwise, <see langword="false"/>.</param>
        /// <returns>The resized texture.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="texture"/> is <see langword="null"/>.
        /// </exception>
        public static Texture ResizeAndGenerateMipmaps(Texture texture, int width, int height, float inputGamma, float outputGamma, bool generateMipmaps, bool hasAlpha, bool hasFractionalAlpha, bool premultipliedAlpha)
        {
            if (texture == null)
            throw new ArgumentNullException("texture");

              // NVIDIA Texture Tools expect BGRA 8:8:8:8.
              if (texture.Description.Format != TextureFormat.B8G8R8A8_UNorm)
            throw new ArgumentException("Texture format needs to be B8G8R8A8_UNORM.", "texture");

              if (texture.Description.Dimension != TextureDimension.TextureCube && texture.Description.ArraySize > 1)
            throw new NotSupportedException("Resizing and mipmap generation for texture arrays is not supported.");
              if (texture.Description.Dimension == TextureDimension.Texture3D)
            throw new NotSupportedException("Resizing and mipmap generation for volume textures is not supported.");

              // ----- InputOptions
              var inputOptions = new InputOptions();
              inputOptions.SetAlphaMode(hasAlpha ? (premultipliedAlpha ? AlphaMode.Premultiplied : AlphaMode.Transparency)
                                         : AlphaMode.None);
              inputOptions.SetFormat(InputFormat.BGRA_8UB);
              inputOptions.SetGamma(inputGamma, outputGamma);
              inputOptions.SetMipmapFilter(MipmapFilter.Box);
              inputOptions.SetMipmapGeneration(generateMipmaps);
              bool roundToPowerOfTwo = (width != texture.Description.Width || height != texture.Description.Height);
              inputOptions.SetRoundMode(roundToPowerOfTwo ? RoundMode.ToNextPowerOfTwo : RoundMode.None);
              inputOptions.SetWrapMode(WrapMode.Mirror);

              var description = texture.Description;
              bool isCube = description.Dimension == TextureDimension.TextureCube;
              var textureType = isCube ? TextureType.TextureCube : TextureType.Texture2D;
              inputOptions.SetTextureLayout(textureType, description.Width, description.Height, 1);

              for (int arrayIndex = 0; arrayIndex < description.ArraySize; arrayIndex++)
              {
            for (int mipIndex = 0; mipIndex < description.MipLevels; mipIndex++)
            {
              int index = texture.GetImageIndex(mipIndex, arrayIndex, 0);
              var image = texture.Images[index];
              var handle = GCHandle.Alloc(image.Data, GCHandleType.Pinned);
              inputOptions.SetMipmapData(handle.AddrOfPinnedObject(), image.Width, image.Height, 1, arrayIndex, mipIndex);
              handle.Free();
            }
              }

              // ----- OutputOptions
              var outputOptions = new OutputOptions();
              outputOptions.SetOutputHeader(false);
              outputOptions.Error += OnError;

              description.Format = TextureFormat.R8G8B8A8_UNorm;
              description.Width = width;
              description.Height = height;
              description.MipLevels = generateMipmaps ? CalculateMipLevels(width, height) : 1;
              var resizedTexture = new Texture(description);
              var outputHandler = new OutputHandler(resizedTexture);
              outputOptions.SetOutputHandler(outputHandler.BeginImage, outputHandler.WriteData);

              // ----- CompressionOptions
              var compressionOptions = new CompressionOptions();
              compressionOptions.SetFormat(Format.RGBA);
              compressionOptions.SetPixelFormat(32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
              compressionOptions.SetQuality(Quality.Normal);

              // ----- Run NVTT
              try
              {
            var compressor = new Compressor();
            compressor.Compress(inputOptions, compressionOptions, outputOptions);
              }
              catch (NullReferenceException)
              {
            // Resizing and mipmap generation without compression sometimes causes a
            // NullReferenceException in nvttCompress().
            throw new Exception("NullReferenceException in NVIDIA texture tools. Please try again.");
              }

              return resizedTexture;
        }
Exemplo n.º 5
0
        /// <summary>
        /// Saves the specified texture in DDS format.
        /// </summary>
        /// <param name="texture">The texture.</param>
        /// <param name="stream">The stream to write to.</param>
        /// <param name="flags">Additional options.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="texture"/> or <paramref name="stream"/> is <see langword="null"/>.
        /// </exception>
        public static void Save(Texture texture, Stream stream, DdsFlags flags)
        {
            if (texture == null)
            throw new ArgumentNullException("texture");
              if (stream == null)
            throw new ArgumentNullException("stream");

            #if NET45
              using (var writer = new BinaryWriter(stream, Encoding.Default, true))
            #else
              using (var writer = new BinaryWriter(stream, Encoding.Default))   // Warning: Closes the stream!
            #endif
              {
            var description = texture.Description;
            EncodeDDSHeader(writer, description, flags);

            switch (description.Dimension)
            {
              case TextureDimension.Texture1D:
              case TextureDimension.Texture2D:
              case TextureDimension.TextureCube:
            {
              int index = 0;
              for (int item = 0; item < description.ArraySize; ++item)
              {
                for (int level = 0; level < description.MipLevels; ++level)
                {
                  var image = texture.Images[index];
                  stream.Write(image.Data, 0, image.Data.Length);
                  ++index;
                }
              }
            }
            break;

              case TextureDimension.Texture3D:
            {
              if (description.ArraySize != 1)
                throw new NotSupportedException("Arrays of volume textures are not supported.");

              int d = description.Depth;

              int index = 0;
              for (int level = 0; level < description.MipLevels; ++level)
              {
                for (int slice = 0; slice < d; ++slice)
                {
                  var image = texture.Images[index];
                  stream.Write(image.Data, 0, image.Data.Length);
                  ++index;
                }

                if (d > 1)
                  d >>= 1;
              }
            }
            break;

              default:
            throw new NotSupportedException("The specified texture dimension is not supported.");
            }
              }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Compresses the specified texture using a Block Compression format (BC<i>n</i>).
        /// </summary>
        /// <param name="texture">The uncompressed texture.</param>
        /// <param name="inputGamma">The input gamma.</param>
        /// <param name="outputGamma">The output gamma.</param>
        /// <param name="generateMipmaps">
        /// <see langword="true"/> to generate all mipmap levels; otherwise <see langword="false"/>.
        /// </param>
        /// <param name="hasAlpha">
        /// <see langword="true"/> if <paramref name="texture"/> requires an alpha channel; otherwise,
        /// <see langword="false"/> if <paramref name="texture"/> is opaque.
        /// </param>
        /// <param name="hasFractionalAlpha">
        /// <see langword="true"/> if <paramref name="texture"/> contains fractional alpha values;
        /// otherwise, <see langword="false"/> if <paramref name="texture"/> is opaque or contains only
        /// binary alpha.
        /// </param>
        /// <param name="premultipliedAlpha">
        /// <see langword="true"/> when <paramref name="texture"/> is using premultiplied alpha.;
        /// otherwise, <see langword="false"/>.</param>
        /// <param name="sharpAlpha">
        /// <see langword="true"/> when the texture contains a sharp alpha mask; otherwise
        /// <see langword="false"/>.
        /// </param>
        /// <returns>The compressed texture.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="texture"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Texture width and height need to be equal (square texture) and  a power of two (POT
        /// texture).
        /// </exception>
        internal static Texture CompressBCn(Texture texture, float inputGamma, float outputGamma, bool generateMipmaps, bool hasAlpha, bool hasFractionalAlpha, bool premultipliedAlpha, bool sharpAlpha = false)
        {
            if (texture == null)
            throw new ArgumentNullException("texture");
              if (texture.Description.Dimension == TextureDimension.Texture3D)
            throw new NotSupportedException("Texture compression for volume textures is not supported.");

              // NVIDIA Texture Tools expect BGRA 8:8:8:8.
              texture = texture.ConvertTo(TextureFormat.B8G8R8A8_UNorm);

              // ----- InputOptions
              var inputOptions = new InputOptions();
              inputOptions.SetAlphaMode(hasAlpha ? (premultipliedAlpha ? AlphaMode.Premultiplied : AlphaMode.Transparency)
                                         : AlphaMode.None);
              inputOptions.SetFormat(InputFormat.BGRA_8UB);
              inputOptions.SetGamma(inputGamma, outputGamma);
              inputOptions.SetMipmapFilter(MipmapFilter.Box);
              inputOptions.SetMipmapGeneration(generateMipmaps);
              inputOptions.SetRoundMode(RoundMode.None);  // Size is set explicitly.
              inputOptions.SetWrapMode(WrapMode.Mirror);

              var description = texture.Description;
              bool isCube = description.Dimension == TextureDimension.TextureCube;
              var textureType = isCube ? TextureType.TextureCube : TextureType.Texture2D;
              inputOptions.SetTextureLayout(textureType, description.Width, description.Height, 1);

              for (int arrayIndex = 0; arrayIndex < description.ArraySize; arrayIndex++)
              {
            for (int mipIndex = 0; mipIndex < description.MipLevels; mipIndex++)
            {
              int index = texture.GetImageIndex(mipIndex, arrayIndex, 0);
              var image = texture.Images[index];
              var handle = GCHandle.Alloc(image.Data, GCHandleType.Pinned);
              inputOptions.SetMipmapData(handle.AddrOfPinnedObject(), image.Width, image.Height, 1, arrayIndex, mipIndex);
              handle.Free();
            }
              }

              // ----- OutputOptions
              var outputOptions = new OutputOptions();
              outputOptions.SetOutputHeader(false);
              outputOptions.Error += OnError;

              Format compressedFormat;
              if (hasAlpha)
              {
            if (sharpAlpha)
            {
              compressedFormat = Format.BC2;
              description.Format = TextureFormat.BC2_UNorm;
            }
            else
            {
              compressedFormat = Format.BC3;
              description.Format = TextureFormat.BC3_UNorm;
            }
              }
              else
              {
            compressedFormat = Format.BC1;
            description.Format = TextureFormat.BC1_UNorm;
              }
              var compressedTexture = new Texture(description);
              var outputHandler = new OutputHandler(compressedTexture);
              outputOptions.SetOutputHandler(outputHandler.BeginImage, outputHandler.WriteData);

              // ----- CompressionOptions
              var compressionOptions = new CompressionOptions();
              compressionOptions.SetFormat(compressedFormat);
              compressionOptions.SetQuality(Quality.Normal);

              // ----- Run NVTT
              try
              {
            var compressor = new Compressor();
            compressor.Compress(inputOptions, compressionOptions, outputOptions);
              }
              catch (NullReferenceException)
              {
            throw new Exception("NullReferenceException in NVIDIA texture tools. Please try again.");
              }

              return compressedTexture;
        }
Exemplo n.º 7
0
        /// <summary>
        /// Loads the specified TGA image.
        /// </summary>
        /// <param name="stream">The stream to read from.</param>
        /// <returns>The <see cref="Texture"/> representing the TGA image.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="stream"/> is <see langword="null"/>.
        /// </exception>
        public static Texture Load(Stream stream)
        {
            if (stream == null)
            throw new ArgumentNullException("stream");

              int offset;
              ConversionFlags convFlags;
              var description = DecodeTGAHeader(stream, out offset, out convFlags);
              var texture = new Texture(description);

              stream.Position = offset;
              using (var reader = new BinaryReader(stream, Encoding.Default))
              {
            if ((convFlags & ConversionFlags.RLE) != 0)
              UncompressPixels(reader, texture.Images[0], description.Format, convFlags);
            else
              CopyPixels(reader, texture.Images[0], description.Format, convFlags);
              }

              return texture;
        }
Exemplo n.º 8
0
        /// <summary>
        /// Converts the specified texture to another format.
        /// </summary>
        /// <param name="format">The desired texture format.</param>
        /// <returns>
        /// The texture using <paramref name="format" />. Does nothing (returns <c>this</c>) if texture
        /// already has the desired format.
        /// </returns>
        /// <exception cref="NotSupportedException">
        /// Texture conversion to the specified format is not supported.
        /// </exception>
        public Texture ConvertTo(DataFormat format)
        {
            var srcFormat = Description.Format;
              var dstFormat = format;

              if (srcFormat == dstFormat)
            return this;

              // ----- Direct conversion:
              // srcFormat -> dstFormat
              if (TextureHelper.CanConvert(srcFormat, dstFormat))
              {
            var description = Description;
            description.Format = dstFormat;

            var texture = new Texture(description);

            #if SINGLE_THREADED
            for (int i = 0; i < Images.Count; i++)
            #else
            Parallel.For(0, Images.Count, i =>
            #endif
            {
              TextureHelper.Convert(Images[i], texture.Images[i]);
            }
            #if !SINGLE_THREADED
            );
            #endif

            return texture;
              }

              // ----- Conversion using intermediate formats:
              // srcFormat -> R32G32B32A32_FLOAT -> dstFormat
              if (TextureHelper.CanConvert(srcFormat, DataFormat.R32G32B32A32_FLOAT)
              && TextureHelper.CanConvert(DataFormat.R32G32B32A32_FLOAT, dstFormat))
              {
            var texture = ConvertTo(DataFormat.R32G32B32A32_FLOAT);
            return texture.ConvertTo(dstFormat);
              }

              // srcFormat -> R8G8B8A8_UNORM -> dstFormat
              if (TextureHelper.CanConvert(srcFormat, DataFormat.R8G8B8A8_UNORM)
              && TextureHelper.CanConvert(DataFormat.R8G8B8A8_UNORM, dstFormat))
              {
            var texture = ConvertTo(DataFormat.R8G8B8A8_UNORM);
            return texture.ConvertTo(dstFormat);
              }

              throw new NotSupportedException(string.Format("Texture format conversion from {0} to {1} is not supported.", srcFormat, dstFormat));
        }
Exemplo n.º 9
0
        /// <overloads>
        /// <summary>
        /// Prepares a normal map for compression using DXT5 (a.k.a. DXT5nm).
        /// </summary>
        /// </overloads>
        /// 
        /// <summary>
        /// Prepares a normal map for compression using DXT5 (a.k.a. DXT5nm).
        /// </summary>
        /// <param name="texture">The texture (<see cref="DataFormat.R32G32B32A32_FLOAT"/>).</param>
        /// <param name="invertY"><see langword="true"/> to invert the y component.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="texture"/> is <see langword="null"/>.
        /// </exception>
        public static void ProcessNormals(Texture texture, bool invertY)
        {
            if (texture == null)
            throw new ArgumentNullException("texture");

            #if SINGLE_THREADED
              foreach (var image in texture.Images)
            ProcessNormals(image, invertY);
            #else
              Parallel.ForEach(texture.Images, image => ProcessNormals(image, invertY));
            #endif
        }
Exemplo n.º 10
0
        private static void Resize3D(Texture srcTexture, int srcMipIndex, int srcArrayOrFaceIndex, Texture dstTexture, int dstMipIndex, int dstArrayOrFaceIndex, Filter filter, bool alphaTransparency, TextureAddressMode wrapMode)
        {
            int srcIndex = srcTexture.GetImageIndex(srcMipIndex, srcArrayOrFaceIndex, 0);
              int srcWidth = srcTexture.Images[srcIndex].Width;
              int srcHeight = srcTexture.Images[srcIndex].Height;
              int srcDepth = srcTexture.GetDepth(srcMipIndex);

              int dstIndex = dstTexture.GetImageIndex(dstMipIndex, dstArrayOrFaceIndex, 0);
              int dstWidth = dstTexture.Images[dstIndex].Width;
              int dstHeight = dstTexture.Images[dstIndex].Height;
              int dstDepth = dstTexture.GetDepth(dstMipIndex);

              // Resize volume.
              var kernelX = new PolyphaseKernel(filter, srcWidth, dstWidth, 32);
              var kernelY = new PolyphaseKernel(filter, srcHeight, dstHeight, 32);
              var kernelZ = new PolyphaseKernel(filter, srcDepth, dstDepth, 32);

              var tmpTexture = new Texture(new TextureDescription
              {
            Dimension = TextureDimension.Texture3D,
            Width = dstWidth,
            Height = srcHeight,
            Depth = srcDepth,
            MipLevels = 1,
            ArraySize = 1,
            Format = DataFormat.R32G32B32A32_FLOAT
              });
              var tmpTexture2 = new Texture(new TextureDescription
              {
            Dimension = TextureDimension.Texture3D,
            Width = dstWidth,
            Height = dstHeight,
            Depth = srcDepth,
            MipLevels = 1,
            ArraySize = 1,
            Format = DataFormat.R32G32B32A32_FLOAT
              });

              // ReSharper disable AccessToDisposedClosure
              using (var srcVolume = new VolumeAccessor(srcTexture, srcMipIndex, srcArrayOrFaceIndex))
              using (var tmpVolume = new VolumeAccessor(tmpTexture, 0, 0))
              using (var tmpVolume2 = new VolumeAccessor(tmpTexture2, 0, 0))
              using (var dstVolume = new VolumeAccessor(dstTexture, dstMipIndex, dstArrayOrFaceIndex))
              {
            // Resize horizontally: srcVolume --> tmpVolume
            {
              float scale = (float)tmpVolume.Width / srcVolume.Width;
              float inverseScale = 1.0f / scale;

            #if SINGLE_THREADED
              for (int z = 0; z < tmpVolume.Depth; z++)
            #else
              Parallel.For(0, tmpVolume.Depth, z =>
            #endif
              {
            for (int y = 0; y < tmpVolume.Height; y++)
            {
              // Apply polyphase kernel horizontally.
              for (int x = 0; x < tmpVolume.Width; x++)
              {
                float center = (x + 0.5f) * inverseScale;

                int left = (int)Math.Floor(center - kernelX.Width);
                int right = (int)Math.Ceiling(center + kernelX.Width);
                Debug.Assert(right - left <= kernelX.WindowSize);

                float totalRgbWeights = 0.0f;
                Vector4F sum = new Vector4F();
                for (int i = 0; i < kernelX.WindowSize; i++)
                {
                  Vector4F color = srcVolume.GetPixel(left + i, y, z, wrapMode);

                  const float alphaEpsilon = 1.0f / 256.0f;
                  float alpha = alphaTransparency ? color.W + alphaEpsilon : 1.0f;

                  float weight = kernelX.Weights[x, i];
                  float rgbWeight = weight * alpha;
                  totalRgbWeights += rgbWeight;

                  sum.X += color.X * rgbWeight;
                  sum.Y += color.Y * rgbWeight;
                  sum.Z += color.Z * rgbWeight;
                  sum.W += color.W * weight;
                }

                float f = 1 / totalRgbWeights;
                sum.X *= f;
                sum.Y *= f;
                sum.Z *= f;

                tmpVolume.SetPixel(x, y, z, sum);
              }
            }
              }
            #if !SINGLE_THREADED
              );
            #endif
            }

            // Resize vertically: tmpVolume --> tmpVolume2
            {
              float scale = (float)tmpVolume2.Height / tmpVolume.Height;
              float inverseScale = 1.0f / scale;

            #if SINGLE_THREADED
              for (int z = 0; z < tmpVolume2.Depth; z++)
            #else
              Parallel.For(0, tmpVolume2.Depth, z =>
            #endif
              {
            for (int x = 0; x < tmpVolume2.Width; x++)
            {
              // Apply polyphase kernel vertically.
              for (int y = 0; y < tmpVolume2.Height; y++)
              {
                float center = (y + 0.5f) * inverseScale;

                int left = (int)Math.Floor(center - kernelY.Width);
                int right = (int)Math.Ceiling(center + kernelY.Width);
                Debug.Assert(right - left <= kernelY.WindowSize);

                float totalRgbWeights = 0.0f;
                Vector4F sum = new Vector4F();
                for (int i = 0; i < kernelY.WindowSize; i++)
                {
                  Vector4F color = tmpVolume.GetPixel(x, left + i, z, wrapMode);

                  const float alphaEpsilon = 1.0f / 256.0f;
                  float alpha = alphaTransparency ? color.W + alphaEpsilon : 1.0f;

                  float weight = kernelY.Weights[y, i];
                  float rgbWeight = weight * alpha;
                  totalRgbWeights += rgbWeight;

                  sum.X += color.X * rgbWeight;
                  sum.Y += color.Y * rgbWeight;
                  sum.Z += color.Z * rgbWeight;
                  sum.W += color.W * weight;
                }

                float f = 1 / totalRgbWeights;
                sum.X *= f;
                sum.Y *= f;
                sum.Z *= f;

                tmpVolume2.SetPixel(x, y, z, sum);
              }
            }
              }
            #if !SINGLE_THREADED
              );
            #endif
            }

            // Resize depth: tmpVolume2 --> dstVolume
            {
              float scale = (float)dstVolume.Depth / tmpVolume2.Depth;
              float inverseScale = 1.0f / scale;

            #if SINGLE_THREADED
              for (int y = 0; y < dstVolume.Height; y++)
            #else
              Parallel.For(0, dstVolume.Height, y =>
            #endif
              {
            for (int x = 0; x < dstVolume.Width; x++)
            {
              // Apply polyphase kernel along z direction.
              for (int z = 0; z < dstVolume.Depth; z++)
              {
                float center = (z + 0.5f) * inverseScale;

                int left = (int)Math.Floor(center - kernelZ.Width);
                int right = (int)Math.Ceiling(center + kernelZ.Width);
                Debug.Assert(right - left <= kernelZ.WindowSize);

                float totalRgbWeights = 0.0f;
                Vector4F sum = new Vector4F();
                for (int i = 0; i < kernelZ.WindowSize; i++)
                {
                  Vector4F color = tmpVolume2.GetPixel(x, y, left + i, wrapMode);

                  const float alphaEpsilon = 1.0f / 256.0f;
                  float alpha = alphaTransparency ? color.W + alphaEpsilon : 1.0f;

                  float weight = kernelZ.Weights[z, i];
                  float rgbWeight = weight * alpha;
                  totalRgbWeights += rgbWeight;

                  sum.X += color.X * rgbWeight;
                  sum.Y += color.Y * rgbWeight;
                  sum.Z += color.Z * rgbWeight;
                  sum.W += color.W * weight;
                }

                float f = 1 / totalRgbWeights;
                sum.X *= f;
                sum.Y *= f;
                sum.Z *= f;

                dstVolume.SetPixel(x, y, z, sum);
              }
            }
              }
            #if !SINGLE_THREADED
              );
            #endif
            }
              }
              // ReSharper restore AccessToDisposedClosure
        }
Exemplo n.º 11
0
        /// <overloads>
        /// <summary>
        /// Converts the specified texture/image from linear space to gamma space.
        /// </summary>
        /// </overloads>
        /// 
        /// <summary>
        /// Converts the specified texture from linear space to gamma space.
        /// </summary>
        /// <param name="texture">The texture (<see cref="DataFormat.R32G32B32A32_FLOAT"/>).</param>
        /// <param name="gamma">The gamma value.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="texture"/> is <see langword="null"/>.
        /// </exception>
        public static void LinearToGamma(Texture texture, float gamma)
        {
            if (texture == null)
            throw new ArgumentNullException("texture");

              if (Numeric.AreEqual(gamma, 1.0f))
            return;

              if (gamma <= 0)
              {
            string message = string.Format(
              CultureInfo.InvariantCulture,
              "Invalid gamma value {0}. The gamma correction value must be greater than 0.",
              gamma);
            throw new ArgumentException(message, "gamma");
              }

            #if SINGLE_THREADED
              foreach (var image in texture.Images)
            LinearToGamma(image, gamma);
            #else
              Parallel.ForEach(texture.Images, image => LinearToGamma(image, gamma));
            #endif
        }
Exemplo n.º 12
0
        /// <overloads>
        /// <summary>
        /// Premultiplies the alpha value of the specified texture/image.
        /// </summary>
        /// </overloads>
        /// 
        /// <summary>
        /// Premultiplies the alpha value of the specified texture.
        /// </summary>
        /// <param name="texture">The texture (<see cref="DataFormat.R32G32B32A32_FLOAT"/>).</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="texture"/> is <see langword="null"/>.
        /// </exception>
        public static void PremultiplyAlpha(Texture texture)
        {
            if (texture == null)
            throw new ArgumentNullException("texture");

            #if SINGLE_THREADED
              foreach (var image in texture.Images)
            PremultiplyAlpha(image);
            #else
              Parallel.ForEach(texture.Images, PremultiplyAlpha);
            #endif
        }
Exemplo n.º 13
0
        /// <overloads>
        /// <summary>
        /// Determines whether the specified texture/image uses the alpha channel.
        /// </summary>
        /// </overloads>
        /// 
        /// <summary>
        /// Determines whether the specified texture uses the alpha channel.
        /// </summary>
        /// <param name="texture">The texture.</param>
        /// <param name="hasAlpha">
        /// <see langword="true"/> if <paramref name="texture"/> requires an alpha channel; otherwise,
        /// <see langword="false"/> if <paramref name="texture"/> is opaque.
        /// </param>
        /// <param name="hasFractionalAlpha">
        /// <see langword="true"/> if <paramref name="texture"/> contains fractional alpha values;
        /// otherwise, <see langword="false"/> if <paramref name="texture"/> is opaque or contains only
        /// binary alpha.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="texture"/> is <see langword="null"/>.
        /// </exception>
        public static void HasAlpha(Texture texture, out bool hasAlpha, out bool hasFractionalAlpha)
        {
            if (texture == null)
            throw new ArgumentNullException("texture");

              // Test mip level 0.
              Image[] images;
              switch (texture.Description.Dimension)
              {
            case TextureDimension.Texture1D:
            case TextureDimension.Texture2D:
            case TextureDimension.TextureCube:
              {
            images = new Image[texture.Description.ArraySize];
            for (int arrayIndex = 0; arrayIndex < images.Length; arrayIndex++)
              images[arrayIndex] = texture.Images[texture.GetImageIndex(0, arrayIndex, 0)];
              }
              break;
            case TextureDimension.Texture3D:
              {
            images = new Image[texture.Description.Depth];
            for (int zIndex = 0; zIndex < images.Length; zIndex++)
              images[zIndex] = texture.Images[texture.GetImageIndex(0, 0, zIndex)];
              }
              break;
            default:
              throw new NotSupportedException("The specified texture dimension is not supported.");
              }

              hasAlpha = false;
              hasFractionalAlpha = false;
              foreach (var image in images)
              {
            bool currentHasAlpha, currentHasFractionalAlpha;
            HasAlpha(image, out currentHasAlpha, out currentHasFractionalAlpha);

            hasAlpha = hasAlpha || currentHasAlpha;
            hasFractionalAlpha = currentHasFractionalAlpha;
            if (hasFractionalAlpha)
              return;
              }
        }
Exemplo n.º 14
0
        /// <summary>
        /// Mirrors the volume texture along the z-axis.
        /// </summary>
        /// <param name="texture">The texture.</param>
        /// <remarks>
        /// The method does nothing if <paramref name="texture"/> is not a volume texture.
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="texture"/> is <see langword="null"/>.
        /// </exception>
        public static void FlipZ(Texture texture)
        {
            if (texture == null)
            throw new ArgumentNullException("texture");

              var description = texture.Description;
              if (description.Dimension != TextureDimension.Texture3D)
            return;

              for (int level = 0; level < description.MipLevels; level++)
              {
            int baseIndex = texture.GetImageIndex(level, 0, 0);
            for (int z0 = 0; z0 < description.Depth / 2; z0++)
            {
              int z1 = description.Depth - z0 - 1;
              int index0 = baseIndex + z0;
              int index1 = baseIndex + z1;
              var image0 = texture.Images[index0];
              var image1 = texture.Images[index1];
              texture.Images[index0] = image1;
              texture.Images[index1] = image0;
            }
              }
        }
Exemplo n.º 15
0
        /// <overloads>
        /// <summary>
        /// Applies color keying to the specified texture/image.
        /// </summary>
        /// </overloads>
        /// 
        /// <summary>
        /// Applies color keying to the specified texture (<see cref="DataFormat.R8G8B8A8_UNORM"/>).
        /// </summary>
        /// <param name="texture">The texture (<see cref="DataFormat.R8G8B8A8_UNORM"/>).</param>
        /// <param name="r">The red component of the color key.</param>
        /// <param name="g">The green component of the color key.</param>
        /// <param name="b">The blue component of the color key.</param>
        /// <param name="a">The alpha component of the color key.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="texture"/> is <see langword="null"/>.
        /// </exception>
        public static void ApplyColorKey(Texture texture, byte r, byte g, byte b, byte a)
        {
            if (texture == null)
            throw new ArgumentNullException("texture");
              if (BitsPerPixel(texture.Description.Format) != 32)
            throw new NotSupportedException(string.Format("The texture format ({0}) is not supported.", texture.Description.Format));

            #if SINGLE_THREADED
              foreach (var image in texture.Images)
            ApplyColorKey(image, r, g, b, a);
            #else
              Parallel.ForEach(texture.Images, image => ApplyColorKey(image, r, g, b, a));
            #endif
        }
Exemplo n.º 16
0
 /// <overloads>
 /// <summary>
 /// Resizes a texture/image.
 /// </summary>
 /// </overloads>
 /// 
 /// <summary>
 /// Resizes a 2D texture or 3D (volume) texture.
 /// </summary>
 /// <param name="srcTexture">The input texture.</param>
 /// <param name="srcMipIndex">The mipmap level of the input image.</param>
 /// <param name="srcArrayOrFaceIndex">
 /// The array index (or the face index for cube maps) of the input image. Must be 0 for volume
 /// textures.
 /// </param>
 /// <param name="dstTexture">The output texture.</param>
 /// <param name="dstMipIndex">The mipmap level of the output image.</param>
 /// <param name="dstArrayOrFaceIndex">
 /// The array index (or the face index for cube maps) of the output image. Must be 0 for volume
 /// textures.
 /// </param>
 /// <param name="filter">The filter to use for resizing.</param>
 /// <param name="alphaTransparency">
 /// <see langword="true"/> if the image contains uses non-premultiplied alpha; otherwise,
 /// <see langword="false"/> if the image uses premultiplied alpha or has no alpha.
 /// </param>
 /// <param name="wrapMode">
 /// The texture address mode that will be used for sampling the at runtime.
 /// </param>
 public static void Resize(Texture srcTexture, int srcMipIndex, int srcArrayOrFaceIndex, Texture dstTexture, int dstMipIndex, int dstArrayOrFaceIndex, ResizeFilter filter, bool alphaTransparency, TextureAddressMode wrapMode)
 {
     Resize(srcTexture, srcMipIndex, srcArrayOrFaceIndex, dstTexture, dstMipIndex, dstArrayOrFaceIndex, GetFilter(filter), alphaTransparency, wrapMode);
 }
Exemplo n.º 17
0
        private static void Tests(Texture texture)
        {
            //var testTexture = texture.ConvertTo(TextureFormat.R32G32B32A32_Float);
            //TextureHelper.FlipX(testTexture);
            //testTexture = testTexture.ConvertTo(TextureFormat.R8G8B8A8_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\FlipX.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //testTexture = texture.ConvertTo(TextureFormat.R32G32B32A32_Float);
            //TextureHelper.FlipY(testTexture);
            //testTexture = testTexture.ConvertTo(TextureFormat.R8G8B8A8_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\FlipY.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //testTexture = texture.ConvertTo(TextureFormat.R32G32B32A32_Float);
            //testTexture = TextureHelper.Rotate(testTexture, 90);
            //testTexture = testTexture.ConvertTo(TextureFormat.R8G8B8A8_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\Rotate90.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //testTexture = texture.ConvertTo(TextureFormat.R32G32B32A32_Float);
            //testTexture = TextureHelper.Rotate(testTexture, 180);
            //testTexture = testTexture.ConvertTo(TextureFormat.R8G8B8A8_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\Rotate180.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //testTexture = texture.ConvertTo(TextureFormat.R32G32B32A32_Float);
            //testTexture = TextureHelper.Rotate(testTexture, 270);
            //testTexture = testTexture.ConvertTo(TextureFormat.R8G8B8A8_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\Rotate270.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //var testTexture = texture.ConvertTo(TextureFormat.R32G32B32A32_Float);
            //testTexture = testTexture.Resize(1000, 1000, 1, ResizeFilter.Box, false, WrapMode.Clamp);
            //testTexture = testTexture.ConvertTo(TextureFormat.R8G8B8A8_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\Resize1000.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //testTexture = texture.ConvertTo(TextureFormat.R32G32B32A32_Float);
            //testTexture = testTexture.Resize(200, 100, 1, ResizeFilter.Box, false, WrapMode.Clamp);
            //testTexture = testTexture.ConvertTo(TextureFormat.R8G8B8A8_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\Resize200x100.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //var testTexture = texture.ConvertTo(TextureFormat.R32G32B32A32_Float);
            //testTexture = testTexture.Resize(1024, 1024, 1, ResizeFilter.Box, true, WrapMode.Repeat);
            //testTexture.GenerateMipmaps(ResizeFilter.Box, true, WrapMode.Repeat);
            //testTexture = testTexture.ConvertTo(TextureFormat.R8G8B8A8_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\Mipmaps.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //var testTexture = texture.ConvertTo(TextureFormat.BC1_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\BC1.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //testTexture = texture.ConvertTo(TextureFormat.BC2_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\BC2.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //testTexture = texture.ConvertTo(TextureFormat.BC3_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\BC3.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);
        }
Exemplo n.º 18
0
        private static void Resize(Texture srcTexture, int srcMipIndex, int srcArrayOrFaceIndex, Texture dstTexture, int dstMipIndex, int dstArrayOrFaceIndex, Filter filter, bool alphaTransparency, TextureAddressMode wrapMode)
        {
            if (srcTexture == null)
            throw new ArgumentNullException("srcTexture");
              if (dstTexture == null)
            throw new ArgumentNullException("dstTexture");

              if (srcTexture == dstTexture && srcMipIndex == dstMipIndex)
            return;

              int srcDepth = srcTexture.GetDepth(srcMipIndex);
              int dstDepth = dstTexture.GetDepth(dstMipIndex);
              if (srcDepth == dstDepth)
              {
            // Resize 2D.
            int srcIndex = srcTexture.GetImageIndex(srcMipIndex, srcArrayOrFaceIndex, 0);
            int srcWidth = srcTexture.Images[srcIndex].Width;
            int srcHeight = srcTexture.Images[srcIndex].Height;

            int dstIndex = dstTexture.GetImageIndex(dstMipIndex, dstArrayOrFaceIndex, 0);
            int dstWidth = dstTexture.Images[dstIndex].Width;
            int dstHeight = dstTexture.Images[dstIndex].Height;

            var kernelX = new PolyphaseKernel(filter, srcWidth, dstWidth, 32);
            var kernelY = new PolyphaseKernel(filter, srcHeight, dstHeight, 32);

            #if SINGLE_THREADED
            for (int z = 0; z < srcDepth; z++)
            #else
            Parallel.For(0, srcDepth, z =>
            #endif
            {
              var srcImage = srcTexture.Images[srcTexture.GetImageIndex(srcMipIndex, srcArrayOrFaceIndex, z)];
              var dstImage = dstTexture.Images[dstTexture.GetImageIndex(dstMipIndex, dstArrayOrFaceIndex, z)];
              Resize2D(srcImage, dstImage, alphaTransparency, wrapMode, kernelX, kernelY);
            }
            #if !SINGLE_THREADED
            );
            #endif
              }
              else
              {
            // Resize 3D.
            Resize3D(srcTexture, srcMipIndex, srcArrayOrFaceIndex, dstTexture, dstMipIndex, dstArrayOrFaceIndex, filter, alphaTransparency, wrapMode);
              }
        }
Exemplo n.º 19
0
        private static Texture DecodeSingleframe(ImagingFactory imagingFactory, WicFlags flags, TextureDescription description, Guid convertGuid, BitmapFrameDecode frame)
        {
            var texture = new Texture(description);
              var image = texture.Images[0];

              if (convertGuid == Guid.Empty)
              {
            frame.CopyPixels(image.Data, image.RowPitch);
              }
              else
              {
            using (var converter = new FormatConverter(imagingFactory))
            {
              converter.Initialize(frame, convertGuid, GetWicDither(flags), null, 0, BitmapPaletteType.Custom);
              converter.CopyPixels(image.Data, image.RowPitch);
            }
              }

              return texture;
        }
Exemplo n.º 20
0
        /// <overloads>
        /// <summary>
        /// Rotates the texture/image counter-clockwise 0°, 90°, 180°, or 270°.
        /// </summary>
        /// </overloads>
        /// 
        /// <summary>
        /// Rotates the specified texture counter-clockwise 0°, 90°, 180°, or 270°.
        /// </summary>
        /// <param name="texture">The texture.</param>
        /// <param name="degrees">
        /// The rotation angle in degrees. Allowed values: -360, -270, -180, -90, 0, 90, 180, 270, 360
        /// </param>
        /// <returns>The rotated texture.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="texture" /> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Invalid rotation angle. Allowed values are -360, -270, -180, -90, 0, 90, 180, 270, 360.
        /// </exception>
        public static Texture Rotate(Texture texture, int degrees)
        {
            if (texture == null)
            throw new ArgumentNullException("texture");

              var description = texture.Description;
              switch (degrees)
              {
            case -360:
            case -180:
            case 0:
            case 180:
            case 360:
              break;

            case -270:
            case -90:
            case 90:
            case 270:
              int width = description.Width;
              int height = description.Height;
              description.Width = height;
              description.Height = width;
              break;

            default:
              throw new ArgumentException("Allowed rotation angles are -360, -270, -180, -90, 0, 90, 180, 270, 360", "degrees");
              }

              var rotatedTexture = new Texture(description);

            #if SINGLE_THREADED
              for (int i = 0; i < texture.Images.Count; i++)
            Rotate(texture.Images[i], rotatedTexture.Images[i], degrees);
            #else
              Parallel.For(0, texture.Images.Count, i => Rotate(texture.Images[i], rotatedTexture.Images[i], degrees));
            #endif

              return rotatedTexture;
        }
Exemplo n.º 21
0
        private static Texture CopyImage(BinaryReader reader, TextureDescription description, ComputePitchFlags cpFlags, ConversionFlags convFlags, uint[] pal8)
        {
            if (reader == null)
            throw new ArgumentNullException("reader");

              if ((convFlags & ConversionFlags.Expand) != 0)
              {
            if ((convFlags & ConversionFlags.Format888) != 0)
              cpFlags |= ComputePitchFlags.Bpp24;
            else if ((convFlags & (ConversionFlags.Format565 | ConversionFlags.Format5551 | ConversionFlags.Format4444 | ConversionFlags.Format8332 | ConversionFlags.FormatA8P8 | ConversionFlags.FormatL16 | ConversionFlags.FormatA8L8)) != 0)
              cpFlags |= ComputePitchFlags.Bpp16;
            else if ((convFlags & (ConversionFlags.Format44 | ConversionFlags.Format332 | ConversionFlags.Pal8 | ConversionFlags.FormatL8)) != 0)
              cpFlags |= ComputePitchFlags.Bpp8;
              }

              var texture = new Texture(description);
              description = texture.Description;  // MipLevel may have been set.

              ScanlineFlags tflags = (convFlags & ConversionFlags.NoAlpha) != 0 ? ScanlineFlags.SetAlpha : 0;
              if ((convFlags & ConversionFlags.Swizzle) != 0)
            tflags |= ScanlineFlags.Legacy;

              switch (description.Dimension)
              {
            case TextureDimension.Texture1D:
            case TextureDimension.Texture2D:
            case TextureDimension.TextureCube:
              {
            int index = 0;
            for (int item = 0; item < description.ArraySize; ++item)
            {
              int width = description.Width;
              int height = description.Height;

              for (int level = 0; level < description.MipLevels; ++level, ++index)
              {
                int sRowPitch, sSlicePitch;
                TextureHelper.ComputePitch(description.Format, width, height, out sRowPitch, out sSlicePitch, cpFlags);

                var image = texture.Images[index];
                if (TextureHelper.IsBCn(description.Format) || TextureHelper.IsPlanar(description.Format))
                {
                  reader.Read(image.Data, 0, image.Data.Length);
                }
                else
                {
                  using (var stream = new MemoryStream(image.Data))
                  using (var writer = new BinaryWriter(stream))
                  {
                    for (int h = 0; h < height; ++h)
                    {
                      if ((convFlags & ConversionFlags.Expand) != 0)
                      {
                        if ((convFlags & (ConversionFlags.Format565 | ConversionFlags.Format5551 | ConversionFlags.Format4444)) != 0)
                        {
                          if (!TextureHelper.ExpandScanline(reader, sRowPitch, (convFlags & ConversionFlags.Format565) != 0 ? DataFormat.B5G6R5_UNORM : DataFormat.B5G5R5A1_UNORM, writer, image.RowPitch, DataFormat.R8G8B8A8_UNORM, tflags))
                            throw new InvalidDataException("Unable to expand format.");
                        }
                        else
                        {
                          LegacyFormat lformat = FindLegacyFormat(convFlags);
                          if (!LegacyExpandScanline(reader, sRowPitch, lformat, writer, image.RowPitch, description.Format, pal8, tflags))
                            throw new InvalidDataException("Unable to expand legacy format.");
                        }
                      }
                      else if ((convFlags & ConversionFlags.Swizzle) != 0)
                      {
                        TextureHelper.SwizzleScanline(reader, sRowPitch, writer, image.RowPitch, description.Format, tflags);
                      }
                      else
                      {
                        TextureHelper.CopyScanline(reader, sRowPitch, writer, image.RowPitch, description.Format, tflags);
                      }
                    }
                  }
                }

                if (width > 1)
                  width >>= 1;

                if (height > 1)
                  height >>= 1;
              }
            }
              }
              break;

            case TextureDimension.Texture3D:
              {
            int index = 0;

            int width = description.Width;
            int height = description.Height;
            int depth = description.Depth;

            for (int level = 0; level < description.MipLevels; ++level)
            {
              int sRowPitch, sSlicePitch;
              TextureHelper.ComputePitch(description.Format, width, height, out sRowPitch, out sSlicePitch, cpFlags);

              for (int slice = 0; slice < depth; ++slice, ++index)
              {
                // We use the same memory organization that Direct3D 11 needs for D3D11_SUBRESOURCE_DATA
                // with all slices of a given miplevel being continuous in memory
                var image = texture.Images[index];

                if (TextureHelper.IsBCn(description.Format))
                {
                  reader.Read(image.Data, 0, image.Data.Length);
                }
                else if (TextureHelper.IsPlanar(description.Format))
                {
                  // Direct3D does not support any planar formats for Texture3D
                  throw new NotSupportedException("Planar texture formats are not support for volume textures.");
                }
                else
                {
                  using (var stream = new MemoryStream(image.Data))
                  using (var writer = new BinaryWriter(stream))
                  {
                    for (int h = 0; h < height; ++h)
                    {
                      if ((convFlags & ConversionFlags.Expand) != 0)
                      {
                        if ((convFlags & (ConversionFlags.Format565 | ConversionFlags.Format5551 | ConversionFlags.Format4444)) != 0)
                        {
                          if (!TextureHelper.ExpandScanline(reader, sRowPitch, (convFlags & ConversionFlags.Format565) != 0 ? DataFormat.B5G6R5_UNORM : DataFormat.B5G5R5A1_UNORM, writer, image.RowPitch, DataFormat.R8G8B8A8_UNORM, tflags))
                            throw new InvalidDataException("Unable to expand format.");
                        }
                        else
                        {
                          LegacyFormat lformat = FindLegacyFormat(convFlags);
                          if (!LegacyExpandScanline(reader, sRowPitch, lformat, writer, image.RowPitch, description.Format, pal8, tflags))
                            throw new InvalidDataException("Unable to expand legacy format.");
                        }
                      }
                      else if ((convFlags & ConversionFlags.Swizzle) != 0)
                      {
                        TextureHelper.SwizzleScanline(reader, sRowPitch, writer, image.RowPitch, description.Format, tflags);
                      }
                      else
                      {
                        TextureHelper.CopyScanline(reader, sRowPitch, writer, image.RowPitch, description.Format, tflags);
                      }
                    }
                  }
                }
              }

              if (width > 1)
                width >>= 1;

              if (height > 1)
                height >>= 1;

              if (depth > 1)
                depth >>= 1;
            }
              }
              break;

            default:
              throw new NotSupportedException("The specified texture dimension is not supported.");
              }

              return texture;
        }
Exemplo n.º 22
0
        /// <overloads>
        /// <summary>
        /// Scales the alpha values to create an equal alpha test coverage across all mipmap levels.
        /// </summary>
        /// </overloads>
        /// 
        /// <summary>
        /// Scales the alpha values to create an equal alpha test coverage across all mipmap levels.
        /// </summary>
        /// <param name="texture">The texture (<see cref="DataFormat.R32G32B32A32_FLOAT"/>).</param>
        /// <param name="referenceAlpha">The reference alpha.</param>
        /// <param name="premultipliedAlpha">
        /// <see langword="true"/> if texture uses premultiplied alpha.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="texture"/> is <see langword="null"/>.
        /// </exception>
        public static void ScaleAlphaToCoverage(Texture texture, float referenceAlpha, bool premultipliedAlpha)
        {
            // See http://the-witness.net/news/2010/09/computing-alpha-mipmaps/.
              // Reference implementation:
              //  NVIDIA Texture Tools - http://code.google.com/p/nvidia-texture-tools/)
              //  file nvidia-texture-tools\src\nvimage\FloatImage.cpp, method scaleAlphaToCoverage()
              //  (Original code marked as "public domain".)

              if (texture == null)
            throw new ArgumentNullException("texture");
              if (texture.Description.Dimension == TextureDimension.Texture3D)
            throw new ArgumentException("Scaling alpha-to-coverage is not supported for volume textures.");

              int mipLevels = texture.Description.MipLevels;
              int arraySize = texture.Description.ArraySize;
            #if SINGLE_THREADED
              for (int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
            #else
              Parallel.For(0, arraySize, arrayIndex =>
            #endif
              {
            int index0 = texture.GetImageIndex(0, arrayIndex, 0);
            float coverage = GetAlphaTestCoverage(texture.Images[index0], referenceAlpha);

            #if SINGLE_THREADED
            for (int mipIndex = 0; mipIndex < mipLevels; mipIndex++)
            #else
            Parallel.For(1, mipLevels, mipIndex =>
            #endif
            {
              int index = texture.GetImageIndex(mipIndex, arrayIndex, 0);
              ScaleAlphaToCoverage(texture.Images[index], referenceAlpha, coverage, premultipliedAlpha);
            }
            #if !SINGLE_THREADED
            );
            #endif
              }
            #if !SINGLE_THREADED
              );
            #endif
        }
Exemplo n.º 23
0
        /// <summary>
        /// Applies color keying to the specified texture (<see cref="DataFormat.R32G32B32A32_FLOAT"/>).
        /// </summary>
        /// <param name="texture">The texture (<see cref="DataFormat.R32G32B32A32_FLOAT"/>).</param>
        /// <param name="colorKey">Color of the color key.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="texture"/> is <see langword="null"/>.
        /// </exception>
        public static void ApplyColorKey(Texture texture, Vector4F colorKey)
        {
            if (texture == null)
            throw new ArgumentNullException("texture");

            #if SINGLE_THREADED
              foreach (var image in texture.Images)
            ApplyColorKey(image, colorKey);
            #else
              Parallel.ForEach(texture.Images, image => ApplyColorKey(image, colorKey));
            #endif
        }
Exemplo n.º 24
0
        private static void Tests(Texture texture)
        {
            //var testTexture = texture.ConvertTo(TextureFormat.R32G32B32A32_Float);
            //TextureHelper.FlipX(testTexture);
            //testTexture = testTexture.ConvertTo(TextureFormat.R8G8B8A8_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\FlipX.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //testTexture = texture.ConvertTo(TextureFormat.R32G32B32A32_Float);
            //TextureHelper.FlipY(testTexture);
            //testTexture = testTexture.ConvertTo(TextureFormat.R8G8B8A8_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\FlipY.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //testTexture = texture.ConvertTo(TextureFormat.R32G32B32A32_Float);
            //testTexture = TextureHelper.Rotate(testTexture, 90);
            //testTexture = testTexture.ConvertTo(TextureFormat.R8G8B8A8_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\Rotate90.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //testTexture = texture.ConvertTo(TextureFormat.R32G32B32A32_Float);
            //testTexture = TextureHelper.Rotate(testTexture, 180);
            //testTexture = testTexture.ConvertTo(TextureFormat.R8G8B8A8_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\Rotate180.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //testTexture = texture.ConvertTo(TextureFormat.R32G32B32A32_Float);
            //testTexture = TextureHelper.Rotate(testTexture, 270);
            //testTexture = testTexture.ConvertTo(TextureFormat.R8G8B8A8_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\Rotate270.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //var testTexture = texture.ConvertTo(TextureFormat.R32G32B32A32_Float);
            //testTexture = testTexture.Resize(1000, 1000, 1, ResizeFilter.Box, false, WrapMode.Clamp);
            //testTexture = testTexture.ConvertTo(TextureFormat.R8G8B8A8_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\Resize1000.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //testTexture = texture.ConvertTo(TextureFormat.R32G32B32A32_Float);
            //testTexture = testTexture.Resize(200, 100, 1, ResizeFilter.Box, false, WrapMode.Clamp);
            //testTexture = testTexture.ConvertTo(TextureFormat.R8G8B8A8_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\Resize200x100.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //var testTexture = texture.ConvertTo(TextureFormat.R32G32B32A32_Float);
            //testTexture = testTexture.Resize(1024, 1024, 1, ResizeFilter.Box, true, WrapMode.Repeat);
            //testTexture.GenerateMipmaps(ResizeFilter.Box, true, WrapMode.Repeat);
            //testTexture = testTexture.ConvertTo(TextureFormat.R8G8B8A8_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\Mipmaps.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //var testTexture = texture.ConvertTo(TextureFormat.BC1_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\BC1.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //testTexture = texture.ConvertTo(TextureFormat.BC2_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\BC2.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);

            //testTexture = texture.ConvertTo(TextureFormat.BC3_UNorm);
            //using (var stream = File.OpenWrite("c:\\temp\\BC3.dds"))
            //  DdsHelper.Save(testTexture, stream, DdsFlags.None);
        }
Exemplo n.º 25
0
        /// <overloads>
        /// <summary>
        /// Expands the texture/image from unsigned normalized values [0, 1] to signed normalized values
        /// [-1, 1]. (Assumes input data is normal map!)
        /// </summary>
        /// </overloads>
        /// 
        /// <summary>
        /// Expands the texture from unsigned normalized values [0, 1] to signed normalized values
        /// [-1, 1]. (Assumes input data is normal map!)
        /// </summary>
        /// <param name="texture">The texture (<see cref="DataFormat.R32G32B32A32_FLOAT"/>).</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="texture"/> is <see langword="null"/>.
        /// </exception>
        public static void UnpackNormals(Texture texture)
        {
            if (texture == null)
            throw new ArgumentNullException("texture");

            #if SINGLE_THREADED
              foreach (var image in texture.Images)
            UnpackNormals(image);
            #else
              Parallel.ForEach(texture.Images, UnpackNormals);
            #endif
        }
Exemplo n.º 26
0
        /// <summary>
        /// Resizes the texture. (If original texture has mipmaps, all mipmap levels are automatically
        /// recreated.)
        /// </summary>
        /// <param name="width">The new width.</param>
        /// <param name="height">The new height.</param>
        /// <param name="depth">The new depth. Must be 1 for 2D textures and cube map textures.</param>
        /// <param name="filter">The filter to use for resizing.</param>
        /// <param name="alphaTransparency">
        /// <see langword="true"/> if the image contains uses non-premultiplied alpha; otherwise,
        /// <see langword="false"/> if the image uses premultiplied alpha or has no alpha.
        /// </param>
        /// <param name="wrapMode">
        /// The texture address mode that will be used for sampling the at runtime.
        /// </param>
        /// <returns>The resized texture.</returns>
        public Texture Resize(int width, int height, int depth, ResizeFilter filter, bool alphaTransparency, TextureAddressMode wrapMode)
        {
            var description = Description;
              description.Width = width;
              description.Height = height;
              description.Depth = depth;

              var resizedTexture = new Texture(description);

              // Resize mipmap level 0.
              for (int arrayIndex = 0; arrayIndex < description.ArraySize; arrayIndex++)
            TextureHelper.Resize(this, 0, arrayIndex, resizedTexture, 0, arrayIndex, filter, alphaTransparency, wrapMode);

              // Regenerate mipmap levels, if necessary.
              if (description.MipLevels > 1)
            resizedTexture.GenerateMipmaps(filter, alphaTransparency, wrapMode);

              return resizedTexture;
        }
Exemplo n.º 27
0
        /// <summary>
        /// Initializes a new instance of the <see cref="VolumeAccessor"/> struct.
        /// </summary>
        /// <param name="texture">The volume texture.</param>
        /// <param name="mipIndex">The mipmap level.</param>
        /// <param name="arrayOrFaceIndex">
        /// The array index for texture arrays, or the face index for cube maps. Must be 0 for volume
        /// textures.
        /// </param>
        public VolumeAccessor(Texture texture, int mipIndex, int arrayOrFaceIndex)
        {
            if (texture == null)
            throw new ArgumentNullException("texture");

              int index = texture.GetImageIndex(mipIndex, arrayOrFaceIndex, 0);
              var image = texture.Images[index];

              _width = image.Width;
              _height = image.Height;
              _depth = texture.Description.Depth;
              _handles = new GCHandle[_depth];
              _intPtrs = new IntPtr[_depth];

              for (int z = 0; z < _depth; z++)
              {
            image = texture.Images[index + z];
            _handles[z] = GCHandle.Alloc(image.Data, GCHandleType.Pinned);
            _intPtrs[z] = _handles[z].AddrOfPinnedObject();
              }
        }