/// <summary> /// Initializes a new instance of the <see cref="cImage"/> class. /// </summary> /// <param name="width">Width of the image.</param> /// <param name="height">Height of the image.</param> public cImage(int width, int height) { this._width = width; this._height = height; this._imageData = new sPixel[width * height]; this.HorizontalOutOfBoundsMode = OutOfBoundsMode.ConstantExtension; this.VerticalOutOfBoundsMode = OutOfBoundsMode.ConstantExtension; }
/// <summary> /// Gets the out of bounds handler or crashes. /// </summary> /// <param name="mode">The mode.</param> /// <returns></returns> public static OutOfBoundsHandler GetHandlerOrCrash(OutOfBoundsMode mode) { OutOfBoundsHandler result; if (_OUT_OF_BOUNDS_HANDLERS.TryGetValue(mode, out result)) { return(result); } throw new NotSupportedException("The OutOfBoundsMode " + mode + " is not supported"); }
private FloatImage(int width, int height, OutOfBoundsMode horizontalOutOfBoundsMode, OutOfBoundsMode verticalOutOfBoundsMode) { this._width = width; this._height = height; this.HorizontalOutOfBoundsMode = horizontalOutOfBoundsMode; this.VerticalOutOfBoundsMode = verticalOutOfBoundsMode; // allocate space var totalElements = width * height; this._redPlane = new float[totalElements]; this._greenPlane = new float[totalElements]; this._bluePlane = new float[totalElements]; this._alphaPlane = new float[totalElements]; }
public ResizeCommand(bool applyToTarget, IImageManipulator manipulator, word width, word height, word percentage, bool maintainAspect, OutOfBoundsMode horizontalBph, OutOfBoundsMode verticalBph, byte count, bool useThresholds, bool useCenteredGrid, float radius) { this._applyToTarget = applyToTarget; this._manipulator = manipulator; this._width = width; this._height = height; this._maintainAspect = maintainAspect; this._horizontalBph = horizontalBph; this._verticalBph = verticalBph; this._count = count; this._useThresholds = useThresholds; this._useCenteredGrid = useCenteredGrid; this._radius = radius; this._percentage = percentage; }
/// <summary> /// Checks coordinates for over-/underflow and does the correction based on the given OutOfBoundsMode. /// </summary> /// <param name="index">The coordinate index.</param> /// <param name="count">The sample count.</param> /// <param name="mode">The mode.</param> /// <returns>A coordinate index that is surely between the bounds.</returns> public static int GetBoundsCheckedCoordinate(int index, int count, OutOfBoundsMode mode) { #if !NET35 Contract.Requires(count > 0, "Number of samples must be above 0"); #endif // check bounds var underflow = index < 0; var overflow = index >= count; if (!(overflow || underflow)) return (index); // find handler var handler = GetHandlerOrCrash(mode); // execute handler return (handler(index, count, overflow, underflow)); }
/// <summary> /// Checks coordinates for over-/underflow and does the correction based on the given OutOfBoundsMode. /// </summary> /// <param name="index">The coordinate index.</param> /// <param name="count">The sample count.</param> /// <param name="mode">The mode.</param> /// <returns>A coordinate index that is surely between the bounds.</returns> public static int GetBoundsCheckedCoordinate(int index, int count, OutOfBoundsMode mode) { #if !NET35 Contract.Requires(count > 0, "Number of samples must be above 0"); #endif // check bounds var underflow = index < 0; var overflow = index >= count; if (!(overflow || underflow)) { return(index); } // find handler var handler = GetHandlerOrCrash(mode); // execute handler return(handler(index, count, overflow, underflow)); }
/// <summary> /// Converts the out of bounds mode to it's textual representation. /// </summary> /// <param name="mode">The mode.</param> /// <returns></returns> private static string _ConvertOutOfBoundsModeToText(OutOfBoundsMode mode) { if (mode == OutOfBoundsMode.ConstantExtension) { return(CONST_BOUNDS_VALUE); } if (mode == OutOfBoundsMode.HalfSampleSymmetric) { return(HALF_BOUNDS_VALUE); } if (mode == OutOfBoundsMode.WholeSampleSymmetric) { return(WHOLE_BOUNDS_VALUE); } if (mode == OutOfBoundsMode.WrapAround) { return(WRAP_BOUNDS_VALUE); } throw new NotImplementedException(); }
/// <summary> /// Converts the out of bounds mode to it's textual representation. /// </summary> /// <param name="mode">The mode.</param> /// <returns></returns> private static string _ConvertOutOfBoundsModeToText(OutOfBoundsMode mode) { switch (mode) { case OutOfBoundsMode.ConstantExtension: return(CONST_BOUNDS_VALUE); case OutOfBoundsMode.HalfSampleSymmetric: return(HALF_BOUNDS_VALUE); case OutOfBoundsMode.WholeSampleSymmetric: return(WHOLE_BOUNDS_VALUE); case OutOfBoundsMode.WrapAround: return(WRAP_BOUNDS_VALUE); case OutOfBoundsMode.Transparent: return(TRANSPARENT_BOUNDS_VALUE); default: throw new NotImplementedException(); } }
/// <summary> /// 1D in-place filtering with a first-order recursive filter pair /// Applies the causal recursive filter /// 1/(1 - alpha z^-1) /// followed by the anti-causal recursive filter /// -alpha/(1 - alpha z). /// The coefficient alpha must satisify |alpha| < 1 for stability. /// /// With respect to boundary handling, filtering is computed with relative /// accuracy Eps = 1e-4 for half- and whole-sample symmetric boundaries and it /// is exact for constant extension. Note, however, that for constant extension /// the infinite grid result is not exactly constant beyond the boundaries /// (rather it decays to constant). /// /// </summary> /// <param name="plane">Data pointer to data to be filtered</param> /// <param name="offset">The offset.</param> /// <param name="stride">stride between successive elements</param> /// <param name="n">number of samples</param> /// <param name="alpha">filter coefficient</param> /// <param name="outOfBoundsMode">the kind of boundary handling to use</param> private static void _PrefilterScan(float[] plane, int offset, int stride, int n, float alpha, OutOfBoundsMode outOfBoundsMode) { Contract.Requires(plane != null); const float eps = 1e-4f; float sum, weight; int i, iEnd; var n0 = (int)Math.Ceiling(Math.Log(eps) / Math.Log(Math.Abs(alpha))); if (n0 > n) n0 = n; switch (outOfBoundsMode) { case OutOfBoundsMode.ConstantExtension: { sum = plane[offset + 0] / (1 - alpha); break; } case OutOfBoundsMode.WholeSampleSymmetric: { sum = plane[offset + 0]; weight = 1; iEnd = n0 * stride; for (i = stride; i < iEnd; i += stride) { weight *= alpha; sum += plane[offset + i] * weight; } break; } default: { /* BOUNDARY_HSYMMETRIC */ sum = plane[offset + 0] * (1 + alpha); weight = alpha; iEnd = n0 * stride; for (i = stride; i < iEnd; i += stride) { weight *= alpha; sum += plane[offset + i] * weight; } break; } } var last = plane[offset + 0] = sum; iEnd = (n - 1) * stride; for (i = stride; i < iEnd; i += stride) { plane[offset + i] += alpha * last; last = plane[offset + i]; } switch (outOfBoundsMode) { case OutOfBoundsMode.ConstantExtension: { last = plane[offset + iEnd] = (alpha * (-plane[offset + iEnd] + (alpha - 1) * alpha * last)) / ((alpha - 1) * (alpha * alpha - 1)); break; } case OutOfBoundsMode.WholeSampleSymmetric: { plane[offset + iEnd] += alpha * last; last = plane[offset + iEnd] = (alpha / (alpha * alpha - 1)) * (plane[offset + iEnd] + alpha * plane[offset + iEnd - stride]); break; } default: { plane[offset + iEnd] += alpha * last; last = plane[offset + iEnd] *= alpha / (alpha - 1); break; } } for (i = iEnd - stride; i >= 0; i -= stride) { plane[offset + i] = alpha * (last - plane[offset + i]); last = plane[offset + i]; } }
/// <summary> /// 1D in-place filtering with a first-order recursive filter pair /// Applies the causal recursive filter /// 1/(1 - alpha z^-1) /// followed by the anti-causal recursive filter /// -alpha/(1 - alpha z). /// The coefficient alpha must satisify |alpha| < 1 for stability. /// /// With respect to boundary handling, filtering is computed with relative /// accuracy Eps = 1e-4 for half- and whole-sample symmetric boundaries and it /// is exact for constant extension. Note, however, that for constant extension /// the infinite grid result is not exactly constant beyond the boundaries /// (rather it decays to constant). /// /// </summary> /// <param name="plane">Data pointer to data to be filtered</param> /// <param name="offset">The offset.</param> /// <param name="stride">stride between successive elements</param> /// <param name="n">number of samples</param> /// <param name="alpha">filter coefficient</param> /// <param name="outOfBoundsMode">the kind of boundary handling to use</param> private static void _PrefilterScan(float[] plane, int offset, int stride, int n, float alpha, OutOfBoundsMode outOfBoundsMode) { Contract.Requires(plane != null); const float eps = 1e-4f; float sum, weight; int i, iEnd; var n0 = (int)Math.Ceiling(Math.Log(eps) / Math.Log(Math.Abs(alpha))); if (n0 > n) { n0 = n; } switch (outOfBoundsMode) { case OutOfBoundsMode.ConstantExtension: { sum = plane[offset + 0] / (1 - alpha); break; } case OutOfBoundsMode.WholeSampleSymmetric: { sum = plane[offset + 0]; weight = 1; iEnd = n0 * stride; for (i = stride; i < iEnd; i += stride) { weight *= alpha; sum += plane[offset + i] * weight; } break; } default: { /* BOUNDARY_HSYMMETRIC */ sum = plane[offset + 0] * (1 + alpha); weight = alpha; iEnd = n0 * stride; for (i = stride; i < iEnd; i += stride) { weight *= alpha; sum += plane[offset + i] * weight; } break; } } var last = plane[offset + 0] = sum; iEnd = (n - 1) * stride; for (i = stride; i < iEnd; i += stride) { plane[offset + i] += alpha * last; last = plane[offset + i]; } switch (outOfBoundsMode) { case OutOfBoundsMode.ConstantExtension: { last = plane[offset + iEnd] = (alpha * (-plane[offset + iEnd] + (alpha - 1) * alpha * last)) / ((alpha - 1) * (alpha * alpha - 1)); break; } case OutOfBoundsMode.WholeSampleSymmetric: { plane[offset + iEnd] += alpha * last; last = plane[offset + iEnd] = (alpha / (alpha * alpha - 1)) * (plane[offset + iEnd] + alpha * plane[offset + iEnd - stride]); break; } default: { plane[offset + iEnd] += alpha * last; last = plane[offset + iEnd] *= alpha / (alpha - 1); break; } } for (i = iEnd - stride; i >= 0; i -= stride) { plane[offset + i] = alpha * (last - plane[offset + i]); last = plane[offset + i]; } }
/// <summary> /// Filters the image. /// </summary> /// <param name="source">The source.</param> /// <param name="method">The method.</param> /// <param name="targetWidth">Width of the target.</param> /// <param name="targetHeight">Height of the target.</param> /// <param name="horizontalBh">The horizontal bounds handling.</param> /// <param name="verticalBh">The vertical bounds handling.</param> /// <param name="useThresholds">if set to <c>true</c> [use thresholds].</param> /// <param name="useCenteredGrid">if set to <c>true</c> [use centered grid].</param> /// <param name="repetitionCount">The repetition count.</param> /// <param name="radius">The radius.</param> /// <returns></returns> internal static cImage FilterImage(cImage source, IImageManipulator method, ushort targetWidth, ushort targetHeight, OutOfBoundsMode horizontalBh, OutOfBoundsMode verticalBh, bool useThresholds, bool useCenteredGrid, byte repetitionCount, float radius) { Contract.Requires(source != null); sPixel.AllowThresholds = useThresholds; source.HorizontalOutOfBoundsMode = horizontalBh; source.VerticalOutOfBoundsMode = verticalBh; cImage result = null; var scaler = method as AScaler; var interpolator = method as Interpolator; var planeExtractor = method as PlaneExtractor; var resampler = method as Resampler; var radiusResampler = method as RadiusResampler; if (scaler != null) { result = source; for (var i = 0; i < repetitionCount; i++) { result = scaler.Apply(result); } } else if (interpolator != null) { if (targetWidth <= 0 || targetHeight <= 0) { MessageBox.Show(Resources.txNeedWidthAndHeightAboveZero, Resources.ttNeedWidthAndHeightAboveZero, MessageBoxButtons.OK, MessageBoxIcon.Stop); } else { result = interpolator.Apply(source, targetWidth, targetHeight); } } else if (planeExtractor != null) { result = planeExtractor.Apply(source); } else if (resampler != null) { if (targetWidth <= 0 || targetHeight <= 0) { MessageBox.Show(Resources.txNeedWidthAndHeightAboveZero, Resources.ttNeedWidthAndHeightAboveZero, MessageBoxButtons.OK, MessageBoxIcon.Stop); } else { result = resampler.Apply(source, targetWidth, targetHeight, useCenteredGrid); } } else if (radiusResampler != null) { if (targetWidth <= 0 || targetHeight <= 0) { MessageBox.Show(Resources.txNeedWidthAndHeightAboveZero, Resources.ttNeedWidthAndHeightAboveZero, MessageBoxButtons.OK, MessageBoxIcon.Stop); } else { result = radiusResampler.Apply(source, targetWidth, targetHeight, radius, useCenteredGrid); } } return(result); }
/// <summary> /// Filters the image. /// </summary> /// <param name="source">The source.</param> /// <param name="method">The method.</param> /// <param name="targetWidth">Width of the target.</param> /// <param name="targetHeight">Height of the target.</param> /// <param name="horizontalBh">The horizontal bounds handling.</param> /// <param name="verticalBh">The vertical bounds handling.</param> /// <param name="useThresholds">if set to <c>true</c> [use thresholds].</param> /// <param name="useCenteredGrid">if set to <c>true</c> [use centered grid].</param> /// <param name="repetitionCount">The repetition count.</param> /// <param name="radius">The radius.</param> /// <returns></returns> internal static cImage FilterImage(cImage source, IImageManipulator method, ushort targetWidth, ushort targetHeight, OutOfBoundsMode horizontalBh, OutOfBoundsMode verticalBh, bool useThresholds, bool useCenteredGrid, byte repetitionCount, float radius) { Contract.Requires(source != null); sPixel.AllowThresholds = useThresholds; source.HorizontalOutOfBoundsMode = horizontalBh; source.VerticalOutOfBoundsMode = verticalBh; cImage result = null; var scaler = method as AScaler; var interpolator = method as Interpolator; var planeExtractor = method as PlaneExtractor; var resampler = method as Resampler; var radiusResampler = method as RadiusResampler; if (scaler != null) { result = source; for (var i = 0; i < repetitionCount; i++) result = scaler.Apply(result); } else if (interpolator != null) if (targetWidth <= 0 || targetHeight <= 0) MessageBox.Show(Resources.txNeedWidthAndHeightAboveZero, Resources.ttNeedWidthAndHeightAboveZero, MessageBoxButtons.OK, MessageBoxIcon.Stop); else result = interpolator.Apply(source, targetWidth, targetHeight); else if (planeExtractor != null) result = planeExtractor.Apply(source); else if (resampler != null) if (targetWidth <= 0 || targetHeight <= 0) MessageBox.Show(Resources.txNeedWidthAndHeightAboveZero, Resources.ttNeedWidthAndHeightAboveZero, MessageBoxButtons.OK, MessageBoxIcon.Stop); else result = resampler.Apply(source, targetWidth, targetHeight, useCenteredGrid); else if (radiusResampler != null) if (targetWidth <= 0 || targetHeight <= 0) MessageBox.Show(Resources.txNeedWidthAndHeightAboveZero, Resources.ttNeedWidthAndHeightAboveZero, MessageBoxButtons.OK, MessageBoxIcon.Stop); else result = radiusResampler.Apply(source, targetWidth, targetHeight, radius, useCenteredGrid); return (result); }
/// <summary> /// Converts the out of bounds mode to it's textual representation. /// </summary> /// <param name="mode">The mode.</param> /// <returns></returns> private static string _ConvertOutOfBoundsModeToText(OutOfBoundsMode mode) { if (mode == OutOfBoundsMode.ConstantExtension) return (CONST_BOUNDS_VALUE); if (mode == OutOfBoundsMode.HalfSampleSymmetric) return (HALF_BOUNDS_VALUE); if (mode == OutOfBoundsMode.WholeSampleSymmetric) return (WHOLE_BOUNDS_VALUE); if (mode == OutOfBoundsMode.WrapAround) return (WRAP_BOUNDS_VALUE); throw new NotImplementedException(); }
/// <summary> /// Gets the out of bounds handler or crashes. /// </summary> /// <param name="mode">The mode.</param> /// <returns></returns> public static OutOfBoundsHandler GetHandlerOrCrash(OutOfBoundsMode mode) { OutOfBoundsHandler result; if (_OUT_OF_BOUNDS_HANDLERS.TryGetValue(mode, out result)) return (result); throw new NotSupportedException("The OutOfBoundsMode " + mode + " is not supported"); }