/// <summary> /// Performs a scaled linear re-projection into the specified target block. /// <br/> /// Uses the given mapping function only to determine the corresponding corner points in the source image, /// uses a linear interpolation to determine intermediate points. /// </summary> /// <param name="source">The image to be re-projected.</param> /// <param name="target">The resulting image to be filled.</param> /// <param name="block">The block being targeted.</param> /// <param name="transformTargetToSource">Mapping function that maps target to source pixels.</param> /// <param name="scale">A factor to apply when re-projecting the block. See code comments in Reproject method above, where this parameter is set up.</param> private static void ScaledReprojection(ArgbImage source, ArgbImage target, ReprojectionBlock block, Func <PointD, PointD> transformTargetToSource, Size scale) { // determine the number of sections of the scaled block var nx = (block.X1 - block.X0 + 1) * scale.Width - 1; var ny = (block.Y1 - block.Y0 + 1) * scale.Height - 1; // Interpolators for upper and lower line of block var upper = InterpolationData.Create(transformTargetToSource(block.LeftTop), transformTargetToSource(block.RightTop), nx); var lower = InterpolationData.Create(transformTargetToSource(block.LeftBottom), transformTargetToSource(block.RightBottom), nx); // total number of color components collected in a color block due to scaling var colorBlockSize = (uint)(scale.Width * scale.Height); for (var x = block.X0; x <= block.X1; ++x) { // setup scale.Width interpolators for interpolating points on the line // defined through upper+n and lower+n, with n=0..(scale.Width-1) var sourcePoint = new InterpolationData[scale.Width]; for (var xsub = 0; xsub < scale.Width; ++xsub) { sourcePoint[xsub] = InterpolationData.Create(upper++, lower++, ny); } for (var y = block.Y0; y <= block.Y1; ++y) { // storage for color components uint a, r, g, b; a = r = g = b = colorBlockSize >> 2; // collect color components of subpixels. // In the inner loop, we'll step our sourcePoint interpolators. for (var ysub = 0; ysub < scale.Height; ++ysub) { for (var xsub = 0; xsub < scale.Width; ++sourcePoint[xsub], ++xsub) { var color = source[sourcePoint[xsub].x, sourcePoint[xsub].y]; a += (color >> 24) & 0xff; r += (color >> 16) & 0xff; g += (color >> 8) & 0xff; b += color & 0xff; } } // average the collected color components and set the target pixel target[x, y] = ((a / colorBlockSize) << 24) | ((r / colorBlockSize) << 16) | ((g / colorBlockSize) << 8) | (b / colorBlockSize); } } }
/// <summary> /// Performs a scaled linear re-projection into the specified target block. /// <br/> /// Uses the given mapping function only to determine the corresponding corner points in the source image, /// uses a linear interpolation to determine intermediate points. /// </summary> /// <param name="source">The image to be re-projected.</param> /// <param name="target">The resulting image to be filled.</param> /// <param name="block">The block being targeted.</param> /// <param name="transformTargetToSource">Mapping function that maps target to source pixels.</param> /// <param name="scaleY">A factor to apply when re-projecting the block. See code comments in Reproject method above, where this parameter is set up.</param> private static void VerticallyScaledReprojection(ArgbImage source, ArgbImage target, ReprojectionBlock block, Func <PointD, PointD> transformTargetToSource, int scaleY) { // determine the number of sections of the scaled block var nx = block.X1 - block.X0; var ny = (block.Y1 - block.Y0 + 1) * scaleY - 1; // Interpolators for upper and lower line of block var upper = InterpolationData.Create(transformTargetToSource(block.LeftTop), transformTargetToSource(block.RightTop), nx); var lower = InterpolationData.Create(transformTargetToSource(block.LeftBottom), transformTargetToSource(block.RightBottom), nx); // total number of color components collected in a color block due to scaling var colorBlockSize = (uint)scaleY; for (var x = block.X0; x <= block.X1; ++x, ++upper, ++lower) { // setup interpolator for interpolating points on the line defined through upper and lower var sourcePoint = InterpolationData.Create(upper, lower, ny); for (var y = block.Y0; y <= block.Y1; ++y) { // storage for color components uint a, r, g, b; a = r = g = b = colorBlockSize >> 2; // collect color components of sub pixels. // In the inner loop, we'll step our sourcePoint interpolators. for (var ysub = 0; ysub < scaleY; ++ysub, ++sourcePoint) { var color = source[sourcePoint.x, sourcePoint.y]; a += (color >> 24) & 0xff; r += (color >> 16) & 0xff; g += (color >> 8) & 0xff; b += color & 0xff; } // average the collected color components and set the target pixel target[x, y] = ((a / colorBlockSize) << 24) | ((r / colorBlockSize) << 16) | ((g / colorBlockSize) << 8) | (b / colorBlockSize); } } }
/// <summary> /// Performs a unscaled linear re-projection into the specified target block. /// <br/> /// Uses the given mapping function only to determine the corresponding corner points in the source image, /// uses a linear interpolation to determine intermediate points. /// </summary> /// <param name="source">The image to be re-projected.</param> /// <param name="target">The resulting image to be filled.</param> /// <param name="block">The block being targeted.</param> /// <param name="transformTargetToSource">Mapping function that maps target to source pixels.</param> private static void UnscaledReprojection(ArgbImage source, ArgbImage target, ReprojectionBlock block, Func <PointD, PointD> transformTargetToSource) { // Interpolators for upper and lower line of block var upper = InterpolationData.Create(transformTargetToSource(block.LeftTop), transformTargetToSource(block.RightTop), block.X1 - block.X0); var lower = InterpolationData.Create(transformTargetToSource(block.LeftBottom), transformTargetToSource(block.RightBottom), block.X1 - block.X0); for (var x = block.X0; x <= block.X1; ++x, ++upper, ++lower) { // interpolator for points on the current line defined through upper and lower var sourcePoint = InterpolationData.Create(upper, lower, block.Y1 - block.Y0); for (var y = block.Y0; y <= block.Y1; ++y, ++sourcePoint) { target[x, y] = source[sourcePoint.x, sourcePoint.y]; } } }