private static void _ScaleScan(float[] dest, int destOrigin, int destStride, int destWidth, float[] src, int srcOrigin, int srcStride, ScaleScanFilter filter) { Contract.Requires(dest != null); Contract.Requires(src != null); var coeffIndex = 0; var destIndex = 0; for (var x = 0; x < destWidth; x++) { var srcIndex = filter.Pos[x] * srcStride; var sum = 0f; for (var k = 0; k < filter.Width; k++, srcIndex += srcStride) { sum += filter.Coeff[coeffIndex + k] * src[srcOrigin + srcIndex]; } dest[destOrigin + destIndex] = sum; destIndex += destStride; coeffIndex += filter.Width; } }
private static void _ScaleScan(float[] dest, int destOrigin, int destStride, int destWidth, float[] src, int srcOrigin, int srcStride, ScaleScanFilter filter) { Contract.Requires(dest != null); Contract.Requires(src != null); var coeffIndex = 0; var destIndex = 0; for (var x = 0; x < destWidth; x++) { var srcIndex = filter.Pos[x] * srcStride; var sum = 0f; for (var k = 0; k < filter.Width; k++, srcIndex += srcStride) sum += filter.Coeff[coeffIndex + k] * src[srcOrigin + srcIndex]; dest[destOrigin + destIndex] = sum; destIndex += destStride; coeffIndex += filter.Width; } }
/// <summary> /// Create scanline interpolation filter to be applied with ScaleScan /// This routine creates a scalescanfilter for 1-D interpolation of samples at /// the locations /// XStart + n*XStep, n = 0, ..., DestWidth - 1, /// where the pixels of the source are logically located at the integers. Half- /// sample even symmetric extension is used to handle the boundaries. /// </summary> /// <param name="destWidth">width after interpolation</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="srcWidth">width of the input</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="boundary">boundary handling</param> /// <returns></returns> /// /// private static ScaleScanFilter _MakeScaleScanFilter(int destWidth, float xstart, float xstep, int srcWidth, Kernels.FixedRadiusKernelMethod kernel, float kernelRadius, bool kernelNormalize, OutOfBoundsUtils.OutOfBoundsHandler boundary) { Contract.Requires(kernel != null); var kernelWidth = (int)Math.Ceiling(2 * kernelRadius); var filterWidth = (srcWidth < kernelWidth) ? srcWidth : kernelWidth; var filterCoeff = new float[filterWidth * destWidth]; var filterPos = new short[destWidth]; var result = new ScaleScanFilter { Coeff = filterCoeff, Pos = filterPos, Width = filterWidth }; var maxPos = srcWidth - filterWidth; var coeffIndex = 0; for (var destX = 0; destX < destWidth; destX++) { var srcX = xstart + xstep * destX; var pos = (int)Math.Ceiling(srcX - kernelRadius); if (pos < 0 || maxPos < pos) { filterPos[destX] = (short)(pos <0 ? 0 : pos> maxPos ? maxPos : pos); for (var n = 0; n < filterWidth; n++) { filterCoeff[coeffIndex + n] = 0; } for (var n = 0; n < kernelWidth; n++) { var index = pos + n; if (index < 0 || index >= srcWidth) { index = boundary(index, srcWidth, index < 0); } filterCoeff[coeffIndex + index - filterPos[destX]] += (float)kernel(srcX - index); } } else { filterPos[destX] = (short)pos; for (var n = 0; n < filterWidth; n++) { filterCoeff[coeffIndex + n] = (float)kernel(srcX - (pos + n)); } } if (kernelNormalize) /* Normalize */ { var sum = 0f; for (var n = 0; n < filterWidth; n++) { sum += filterCoeff[coeffIndex + n]; } for (var n = 0; n < filterWidth; n++) { filterCoeff[coeffIndex + n] /= sum; } } coeffIndex += filterWidth; } return(result); }
/// <summary> /// Create scanline interpolation filter to be applied with ScaleScan /// This routine creates a scalescanfilter for 1-D interpolation of samples at /// the locations /// XStart + n*XStep, n = 0, ..., DestWidth - 1, /// where the pixels of the source are logically located at the integers. Half- /// sample even symmetric extension is used to handle the boundaries. /// </summary> /// <param name="destWidth">width after interpolation</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="srcWidth">width of the input</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="boundary">boundary handling</param> /// <returns></returns> /// /// private static ScaleScanFilter _MakeScaleScanFilter(int destWidth, float xstart, float xstep, int srcWidth, Kernels.FixedRadiusKernelMethod kernel, float kernelRadius, bool kernelNormalize, OutOfBoundsUtils.OutOfBoundsHandler boundary) { Contract.Requires(kernel != null); var kernelWidth = (int)Math.Ceiling(2 * kernelRadius); var filterWidth = (srcWidth < kernelWidth) ? srcWidth : kernelWidth; var filterCoeff = new float[filterWidth * destWidth]; var filterPos = new short[destWidth]; var result = new ScaleScanFilter { Coeff = filterCoeff, Pos = filterPos, Width = filterWidth }; var maxPos = srcWidth - filterWidth; var coeffIndex = 0; for (var destX = 0; destX < destWidth; destX++) { var srcX = xstart + xstep * destX; var pos = (int)Math.Ceiling(srcX - kernelRadius); if (pos < 0 || maxPos < pos) { filterPos[destX] = (short)(pos < 0 ? 0 : pos > maxPos ? maxPos : pos); for (var n = 0; n < filterWidth; n++) filterCoeff[coeffIndex + n] = 0; for (var n = 0; n < kernelWidth; n++) { var index = pos + n; if (index < 0 || index >= srcWidth) index = boundary(index, srcWidth,index<0); filterCoeff[coeffIndex + index - filterPos[destX]] += (float) kernel(srcX - index); } } else { filterPos[destX] = (short)pos; for (var n = 0; n < filterWidth; n++) filterCoeff[coeffIndex + n] = (float)kernel(srcX - (pos + n)); } if (kernelNormalize) /* Normalize */ { var sum = 0f; for (var n = 0; n < filterWidth; n++) sum += filterCoeff[coeffIndex + n]; for (var n = 0; n < filterWidth; n++) filterCoeff[coeffIndex + n] /= sum; } coeffIndex += filterWidth; } return (result); }