Exemplo n.º 1
0
        /// <summary>
        /// Computes the weights to apply at each pixel when resizing.
        /// </summary>
        /// <param name="sampler">The <see cref="IResampler"/></param>
        /// <param name="destinationSize">The destination size</param>
        /// <param name="sourceSize">The source size</param>
        /// <param name="memoryAllocator">The <see cref="MemoryAllocator"/> to use for buffer allocations</param>
        /// <returns>The <see cref="ResizeKernelMap"/></returns>
        public static ResizeKernelMap Calculate(
            IResampler sampler,
            int destinationSize,
            int sourceSize,
            MemoryAllocator memoryAllocator)
        {
            double ratio = (double)sourceSize / destinationSize;
            double scale = ratio;

            if (scale < 1)
            {
                scale = 1;
            }

            int radius = (int)TolerantMath.Ceiling(scale * sampler.Radius);

            // 'ratio' is a rational number.
            // Multiplying it by LCM(sourceSize, destSize)/sourceSize will result in a whole number "again".
            // This value is determining the length of the periods in repeating kernel map rows.
            int period = ImageMaths.LeastCommonMultiple(sourceSize, destinationSize) / sourceSize;

            // the center position at i == 0:
            double center0 = (ratio - 1) * 0.5;
            double firstNonNegativeLeftVal = (radius - center0 - 1) / ratio;

            // The number of rows building a "stairway" at the top and the bottom of the kernel map
            // corresponding to the corners of the image.
            // If we do not normalize the kernel values, these rows also fit the periodic logic,
            // however, it's just simpler to calculate them separately.
            int cornerInterval = (int)TolerantMath.Ceiling(firstNonNegativeLeftVal);

            // If firstNonNegativeLeftVal was an integral value, we need firstNonNegativeLeftVal+1
            // instead of Ceiling:
            if (TolerantMath.AreEqual(firstNonNegativeLeftVal, cornerInterval))
            {
                cornerInterval++;
            }

            // If 'cornerInterval' is too big compared to 'period', we can't apply the periodic optimization.
            // If we don't have at least 2 periods, we go with the basic implementation:
            bool hasAtLeast2Periods = 2 * (cornerInterval + period) < destinationSize;

            ResizeKernelMap result = hasAtLeast2Periods
                                         ? new PeriodicKernelMap(
                memoryAllocator,
                sampler,
                sourceSize,
                destinationSize,
                ratio,
                scale,
                radius,
                period,
                cornerInterval)
                                         : new ResizeKernelMap(
                memoryAllocator,
                sampler,
                sourceSize,
                destinationSize,
                destinationSize,
                ratio,
                scale,
                radius);

            result.Initialize();

            return(result);
        }
Exemplo n.º 2
0
        public void LeastCommonMultiple(int a, int b, int expected)
        {
            int actual = ImageMaths.LeastCommonMultiple(a, b);

            Assert.Equal(expected, actual);
        }