Esempio n. 1
0
        /// <summary>
        /// Create the mipmaps by downsampling using a filter.
        /// </summary>
        public void GenerateMipmaps(Filter filter)
        {
            for (int i = 1; i < Levels; i++)
            {
                TextureData2D src = Data[i - 1];
                TextureData2D dst = Data[i];

                int srcWidth  = src.GetWidth();
                int srcHeight = src.GetHeight();

                int dstWidth  = dst.GetWidth();
                int dstHeight = dst.GetHeight();

                float[] tmp = new float[dstWidth * srcHeight * Channels];

                PolyphaseKernel xKernel = new PolyphaseKernel(filter, srcWidth, dstWidth, 32);
                PolyphaseKernel yKernel = new PolyphaseKernel(filter, srcHeight, dstHeight, 32);

                for (int y = 0; y < srcHeight; y++)
                {
                    xKernel.ApplyHorizontal(y, src, tmp, dstWidth);
                }

                for (int x = 0; x < dstWidth; x++)
                {
                    yKernel.ApplyVertical(x, tmp, dstWidth, srcHeight, Channels, dst);
                }
            }
        }
    private static void Resize(Image srcImage, Image dstImage, Filter filter, bool alphaTransparency, TextureAddressMode wrapMode)
    {
      if (srcImage == null)
        throw new ArgumentNullException("srcImage");
      if (dstImage == null)
        throw new ArgumentNullException("dstImage");
      if (filter == null)
        throw new ArgumentNullException("filter");

      var kernelX = new PolyphaseKernel(filter, srcImage.Width, dstImage.Width, 32);
      var kernelY = new PolyphaseKernel(filter, srcImage.Height, dstImage.Height, 32);

      Resize2D(srcImage, dstImage, alphaTransparency, wrapMode, kernelX, kernelY);
    }
    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);
      }
    }
    private static void Resize2D(Image srcImage, Image dstImage, bool alphaTransparency, TextureAddressMode wrapMode, PolyphaseKernel kernelX, PolyphaseKernel kernelY)
    {
      var tmpImage = new Image(dstImage.Width, srcImage.Height, srcImage.Format);

      // ReSharper disable AccessToDisposedClosure
      using (var srcImage4F = new ImageAccessor(srcImage))
      using (var tmpImage4F = new ImageAccessor(tmpImage))
      using (var dstImage4F = new ImageAccessor(dstImage))
      {
        // Resize horizontally: srcImage --> tmpImage
        {
          float scale = (float)tmpImage4F.Width / srcImage4F.Width;
          float inverseScale = 1.0f / scale;

#if SINGLE_THREADED
          for (int y = 0; y < tmpImage4F.Height; y++)
#else
          Parallel.For(0, tmpImage4F.Height, y =>
#endif
          {
            // Apply polyphase kernel horizontally.
            for (int x = 0; x < tmpImage4F.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 = srcImage4F.GetPixel(left + i, y, wrapMode);

                //if (Numeric.IsNaN(color.X) || Numeric.IsNaN(color.Y) || Numeric.IsNaN(color.Z) || Numeric.IsNaN(color.W)
                //   || color.X < 0 || color.Y < 0 || color.Z < 0 || color.W < 0
                //   || color.X > 1 || color.Y > 1 || color.Z > 1 || color.W > 1)
                //  Debugger.Break();

                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;

                //if (Numeric.IsNaN(sum.X) || Numeric.IsNaN(sum.Y) || Numeric.IsNaN(sum.Z) || Numeric.IsNaN(sum.W)
                //   || sum.X < 0 || sum.Y < 0 || sum.Z < 0 || sum.W < 0
                //   || sum.X > 1 || sum.Y > 1 || sum.Z > 1 || sum.W > 1)
                //  Debugger.Break();
              }

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

              //if (Numeric.IsNaN(sum.X) || Numeric.IsNaN(sum.Y) || Numeric.IsNaN(sum.Z) || Numeric.IsNaN(sum.W)
              //   || sum.X < 0 || sum.Y < 0 || sum.Z < 0 || sum.W < 0
              //   || sum.X > 1 || sum.Y > 1 || sum.Z > 1 || sum.W > 1)
              //  Debugger.Break();

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

        // Resize vertically: tmpImage --> dstImage
        {
          float scale = (float)dstImage4F.Height / tmpImage4F.Height;
          float inverseScale = 1.0f / scale;

#if SINGLE_THREADED
          for (int x = 0; x < dstImage4F.Width; x++)
#else
          Parallel.For(0, dstImage4F.Width, x =>
#endif
          {
            // Apply polyphase kernel vertically.
            for (int y = 0; y < dstImage4F.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 = tmpImage4F.GetPixel(x, left + i, 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;

              dstImage4F.SetPixel(x, y, sum);
            }
          }
#if !SINGLE_THREADED
          );
#endif
        }
      }
      // ReSharper restore AccessToDisposedClosure
    }
    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
    }
Esempio n. 6
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
        }
Esempio n. 7
0
        private static void Resize2D(Image srcImage, Image dstImage, bool alphaTransparency, TextureAddressMode wrapMode, PolyphaseKernel kernelX, PolyphaseKernel kernelY)
        {
            var tmpImage = new Image(dstImage.Width, srcImage.Height, srcImage.Format);

              // ReSharper disable AccessToDisposedClosure
              using (var srcImage4F = new ImageAccessor(srcImage))
              using (var tmpImage4F = new ImageAccessor(tmpImage))
              using (var dstImage4F = new ImageAccessor(dstImage))
              {
            // Resize horizontally: srcImage --> tmpImage
            {
              float scale = (float)tmpImage4F.Width / srcImage4F.Width;
              float inverseScale = 1.0f / scale;

            #if SINGLE_THREADED
              for (int y = 0; y < tmpImage4F.Height; y++)
            #else
              Parallel.For(0, tmpImage4F.Height, y =>
            #endif
              {
            // Apply polyphase kernel horizontally.
            for (int x = 0; x < tmpImage4F.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 = srcImage4F.GetPixel(left + i, y, wrapMode);

                //if (Numeric.IsNaN(color.X) || Numeric.IsNaN(color.Y) || Numeric.IsNaN(color.Z) || Numeric.IsNaN(color.W)
                //   || color.X < 0 || color.Y < 0 || color.Z < 0 || color.W < 0
                //   || color.X > 1 || color.Y > 1 || color.Z > 1 || color.W > 1)
                //  Debugger.Break();

                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;

                //if (Numeric.IsNaN(sum.X) || Numeric.IsNaN(sum.Y) || Numeric.IsNaN(sum.Z) || Numeric.IsNaN(sum.W)
                //   || sum.X < 0 || sum.Y < 0 || sum.Z < 0 || sum.W < 0
                //   || sum.X > 1 || sum.Y > 1 || sum.Z > 1 || sum.W > 1)
                //  Debugger.Break();
              }

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

              //if (Numeric.IsNaN(sum.X) || Numeric.IsNaN(sum.Y) || Numeric.IsNaN(sum.Z) || Numeric.IsNaN(sum.W)
              //   || sum.X < 0 || sum.Y < 0 || sum.Z < 0 || sum.W < 0
              //   || sum.X > 1 || sum.Y > 1 || sum.Z > 1 || sum.W > 1)
              //  Debugger.Break();

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

            // Resize vertically: tmpImage --> dstImage
            {
              float scale = (float)dstImage4F.Height / tmpImage4F.Height;
              float inverseScale = 1.0f / scale;

            #if SINGLE_THREADED
              for (int x = 0; x < dstImage4F.Width; x++)
            #else
              Parallel.For(0, dstImage4F.Width, x =>
            #endif
              {
            // Apply polyphase kernel vertically.
            for (int y = 0; y < dstImage4F.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 = tmpImage4F.GetPixel(x, left + i, 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;

              dstImage4F.SetPixel(x, y, sum);
            }
              }
            #if !SINGLE_THREADED
              );
            #endif
            }
              }
              // ReSharper restore AccessToDisposedClosure
        }
Esempio n. 8
0
        private static void Resize(Image srcImage, Image dstImage, Filter filter, bool alphaTransparency, TextureAddressMode wrapMode)
        {
            if (srcImage == null)
            throw new ArgumentNullException("srcImage");
              if (dstImage == null)
            throw new ArgumentNullException("dstImage");
              if (filter == null)
            throw new ArgumentNullException("filter");

              var kernelX = new PolyphaseKernel(filter, srcImage.Width, dstImage.Width, 32);
              var kernelY = new PolyphaseKernel(filter, srcImage.Height, dstImage.Height, 32);

              Resize2D(srcImage, dstImage, alphaTransparency, wrapMode, kernelX, kernelY);
        }
Esempio n. 9
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);
              }
        }