Esempio n. 1
0
        /*
         * This region is a C++ -> C# conversion from the original sources of Pascal Getreuer <*****@*****.**>
         */
        /// <summary>
        /// Resizes the image to the specified dimensions using the given kernel type.
        /// </summary>
        /// <param name="destWidth">Width of the destination.</param>
        /// <param name="destHeight">Height of the destination.</param>
        /// <param name="interpolationInfo">The interpolation method info.</param>
        /// <param name="centeredGrid">if set to <c>true</c> using a centered grid; otherwise, using top-left aligned.</param>
        /// <returns>
        /// The resized image
        /// </returns>
        private FloatImage _Resize(int destWidth, int destHeight, Kernels.FixedRadiusKernelInfo interpolationInfo, bool centeredGrid)
        {
            var   xScale = (float)destWidth / this.Width;
            var   yScale = (float)destHeight / this.Height;
            var   xStep = 1 / xScale;
            var   yStep = 1 / yScale;
            float xStart, yStart;

            if (centeredGrid)
            {
                xStart = (xStep - 1) / 2;
                yStart = (yStep - 1) / 2;
            }
            else
            {
                xStart = yStart = 0;
            }
            var result = new FloatImage(destWidth, destHeight, this._horizontalOutOfBoundsMode, this._verticalOutOfBoundsMode);

            // prefilter image if necessary
            if (interpolationInfo.PrefilterAlpha != null && interpolationInfo.PrefilterAlpha.Length > 0)
            {
                this._PrefilterImage(interpolationInfo.PrefilterAlpha, interpolationInfo.PrefilterScale);
            }

            // resample
            this._LinScale2D(
                result,
                xStart,
                xStep,
                yStart,
                yStep,
                interpolationInfo.Kernel,
                interpolationInfo.KernelRadius,
                interpolationInfo.KernelNormalize,
                OutOfBoundsUtils.GetHandlerOrCrash(this.HorizontalOutOfBoundsMode),
                OutOfBoundsUtils.GetHandlerOrCrash(this.VerticalOutOfBoundsMode)
                );
            return(result);
        }
Esempio n. 2
0
        /// <summary>
        /// Converts a given image into a floating point one.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="filterRegion">The filter region.</param>
        /// <returns></returns>
        public static FloatImage FromImage(cImage image, Rectangle?filterRegion)
        {
            Contract.Requires(image != null);

            var startX = filterRegion == null ? 0 : Math.Max(0, filterRegion.Value.Left);
            var startY = filterRegion == null ? 0 : Math.Max(0, filterRegion.Value.Top);

            var endX = filterRegion == null ? image.Width : Math.Min(image.Width, filterRegion.Value.Right);
            var endY = filterRegion == null ? image.Height : Math.Min(image.Height, filterRegion.Value.Bottom);

            var width  = endX - startX;
            var height = endY - startY;

            var result = new FloatImage(width, height, image.HorizontalOutOfBoundsMode, image.VerticalOutOfBoundsMode);

            // copy image data
            Parallel.ForEach(
                Partitioner.Create(startY, endY),
                () => 0,
                (range, _, threadStorage) => {
                var i = (range.Item1 - startY) * width;
                for (var y = range.Item1; y < range.Item2; ++y)
                {
                    for (var x = startX; x < endX; ++x)
                    {
                        var color             = image[x, y];
                        result._redPlane[i]   = color.SingleRed;
                        result._greenPlane[i] = color.SingleGreen;
                        result._bluePlane[i]  = color.SingleBlue;
                        result._alphaPlane[i] = color.SingleAlpha;
                        ++i;
                    }
                }
                return(threadStorage);
            },
                _ => { }
                );
            return(result);
        }
Esempio n. 3
0
    /*
     * This region is a C++ -> C# conversion from the original sources of Pascal Getreuer <*****@*****.**>
     */
    /// <summary>
    /// Resizes the image to the specified dimensions using the given kernel type.
    /// </summary>
    /// <param name="destWidth">Width of the destination.</param>
    /// <param name="destHeight">Height of the destination.</param>
    /// <param name="interpolationInfo">The interpolation method info.</param>
    /// <param name="centeredGrid">if set to <c>true</c> using a centered grid; otherwise, using top-left aligned.</param>
    /// <returns>
    /// The resized image
    /// </returns>
    private FloatImage _Resize(int destWidth, int destHeight, Kernels.FixedRadiusKernelInfo interpolationInfo, bool centeredGrid) {
      var xScale = (float)destWidth / this.Width;
      var yScale = (float)destHeight / this.Height;
      var xStep = 1 / xScale;
      var yStep = 1 / yScale;
      float xStart, yStart;
      if (centeredGrid) {
        xStart = (xStep - 1) / 2;
        yStart = (yStep - 1) / 2;
      } else {
        xStart = yStart = 0;
      }
      var result = new FloatImage(destWidth, destHeight, this._horizontalOutOfBoundsMode, this._verticalOutOfBoundsMode);

      // prefilter image if necessary
      if (interpolationInfo.PrefilterAlpha != null && interpolationInfo.PrefilterAlpha.Length > 0)
        this._PrefilterImage(interpolationInfo.PrefilterAlpha, interpolationInfo.PrefilterScale);

      // resample
      this._LinScale2D(
        result,
        xStart,
        xStep,
        yStart,
        yStep,
        interpolationInfo.Kernel,
        interpolationInfo.KernelRadius,
        interpolationInfo.KernelNormalize,
        OutOfBoundsUtils.GetHandlerOrCrash(this.HorizontalOutOfBoundsMode),
        OutOfBoundsUtils.GetHandlerOrCrash(this.VerticalOutOfBoundsMode)
      );
      return (result);
    }
Esempio n. 4
0
    /// <summary>
    /// Scale image with a compact support interpolation kernel
    /// This is a generic linear interpolation routine to scale an image using any
    /// compactly supported interpolation kernel.  The kernel is applied separably
    /// along both dimensions.  Half-sample even symmetric extension is used to
    /// handle the boundaries.
    /// 
    /// The interpolation is computed so that Dest[m + DestWidth*n] is the
    /// interpolation of Src at sampling location
    ///     (XStart + m*XStep, YStart + n*YStep)
    /// for m = 0, ..., DestWidth - 1, n = 0, ..., DestHeight - 1, where the
    /// pixels of Src are located at the integers.
    /// 
    /// The implementation follows the approach taken in ffmpeg's swscale library.
    /// First a "scanline filter" is constructed, a sparse matrix such that
    /// multiplying with a row of the input image produces an interpolated row in
    /// the output image.  Similarly a second matrix is constructed for
    /// interpolating columns.  The interpolation itself is then essentially two
    /// sparse matrix times dense matrix multiplies.
    /// </summary>
    /// <param name="destination">pointer to memory for holding the interpolated image</param>
    /// <param name="xStart">leftmost sampling location (in input coordinates)</param>
    /// <param name="xStep">the length between successive samples (in input coordinates)</param>
    /// <param name="yStart">uppermost sampling location (in input coordinates)</param>
    /// <param name="yStep">the length between successive samples (in input coordinates)</param>
    /// <param name="kernel">interpolation kernel function to use</param>
    /// <param name="kernelRadius">kernel support radius</param>
    /// <param name="kernelNormalize">if set to <c>true</c> filter rows are normalized to sum to 1</param>
    /// <param name="horizontalOutOfBoundsHandler">The horizontal out of bounds handler.</param>
    /// <param name="verticalOutOfBoundsHandler">The vertical out of bounds handler.</param>
    private void _LinScale2D(FloatImage destination, float xStart, float xStep, float yStart, float yStep, Kernels.FixedRadiusKernelMethod kernel, float kernelRadius, bool kernelNormalize, OutOfBoundsUtils.OutOfBoundsHandler horizontalOutOfBoundsHandler, OutOfBoundsUtils.OutOfBoundsHandler verticalOutOfBoundsHandler) {
      Contract.Requires(destination != null);
      Contract.Requires(kernel != null);
      Contract.Requires(!(kernelRadius < 0));

      var srcWidth = this.Width;
      var srcHeight = this.Height;

      var destHeight = destination.Height;
      var destWidth = destination.Width;

      var buffer = new float[srcWidth * destHeight];
      var hFilter = _MakeScaleScanFilter(destWidth, xStart, xStep, srcWidth, kernel, kernelRadius, kernelNormalize, horizontalOutOfBoundsHandler);
      var vFilter = _MakeScaleScanFilter(destHeight, yStart, yStep, srcHeight, kernel, kernelRadius, kernelNormalize, verticalOutOfBoundsHandler);

      foreach (var plane in new[] {
        Tuple.Create(this._redPlane,destination._redPlane),
        Tuple.Create(this._greenPlane,destination._greenPlane),
        Tuple.Create(this._bluePlane,destination._bluePlane),
        Tuple.Create(this._alphaPlane,destination._alphaPlane),
      }) {
        for (var x = 0; x < srcWidth; x++)
          _ScaleScan(buffer, x, srcWidth, destHeight, plane.Item1, x, srcWidth, vFilter);

        for (var y = 0; y < destHeight; y++)
          _ScaleScan(plane.Item2, y * destWidth, 1, destWidth, buffer, y * srcWidth, 1, hFilter);
      }
    }
Esempio n. 5
0
    /// <summary>
    /// Converts a given image into a floating point one.
    /// </summary>
    /// <param name="image">The image.</param>
    /// <param name="filterRegion">The filter region.</param>
    /// <returns></returns>
    public static FloatImage FromImage(cImage image, Rectangle? filterRegion) {
      Contract.Requires(image != null);

      var startX = filterRegion == null ? 0 : Math.Max(0, filterRegion.Value.Left);
      var startY = filterRegion == null ? 0 : Math.Max(0, filterRegion.Value.Top);

      var endX = filterRegion == null ? image.Width : Math.Min(image.Width, filterRegion.Value.Right);
      var endY = filterRegion == null ? image.Height : Math.Min(image.Height, filterRegion.Value.Bottom);

      var width = endX - startX;
      var height = endY - startY;

      var result = new FloatImage(width, height, image.HorizontalOutOfBoundsMode, image.VerticalOutOfBoundsMode);

      // copy image data
      Parallel.ForEach(
        Partitioner.Create(startY, endY),
        () => 0,
        (range, _, threadStorage) => {
          var i = (range.Item1 - startY) * width;
          for (var y = range.Item1; y < range.Item2; ++y) {
            for (var x = startX; x < endX; ++x) {
              var color = image[x, y];
              result._redPlane[i] = color.SingleRed;
              result._greenPlane[i] = color.SingleGreen;
              result._bluePlane[i] = color.SingleBlue;
              result._alphaPlane[i] = color.SingleAlpha;
              ++i;
            }
          }
          return (threadStorage);
        },
        _ => { }
      );
      return (result);
    }